| <!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"> |
| <meta name="author" content="Khronos® OpenCL Working Group"> |
| <title>The OpenCL™ Specification</title> |
| <style> |
| /*! normalize.css v2.1.2 | MIT License | git.io/normalize */ |
| /* ========================================================================== HTML5 display definitions ========================================================================== */ |
| /** Correct `block` display not defined in IE 8/9. */ |
| article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { display: block; } |
| |
| /** Correct `inline-block` display not defined in IE 8/9. */ |
| audio, canvas, video { display: inline-block; } |
| |
| /** Prevent modern browsers from displaying `audio` without controls. Remove excess height in iOS 5 devices. */ |
| audio:not([controls]) { display: none; height: 0; } |
| |
| /** Address `[hidden]` styling not present in IE 8/9. Hide the `template` element in IE, Safari, and Firefox < 22. */ |
| [hidden], template { display: none; } |
| |
| script { display: none !important; } |
| |
| /* ========================================================================== Base ========================================================================== */ |
| /** 1. Set default font family to sans-serif. 2. Prevent iOS text size adjust after orientation change, without disabling user zoom. */ |
| html { font-family: sans-serif; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ } |
| |
| /** Remove default margin. */ |
| body { margin: 0; } |
| |
| /* ========================================================================== Links ========================================================================== */ |
| /** Remove the gray background color from active links in IE 10. */ |
| a { background: transparent; } |
| |
| /** Address `outline` inconsistency between Chrome and other browsers. */ |
| a:focus { outline: thin dotted; } |
| |
| /** Improve readability when focused and also mouse hovered in all browsers. */ |
| a:active, a:hover { outline: 0; } |
| |
| /* ========================================================================== Typography ========================================================================== */ |
| /** Address variable `h1` font-size and margin within `section` and `article` contexts in Firefox 4+, Safari 5, and Chrome. */ |
| h1 { font-size: 2em; margin: 0.67em 0; } |
| |
| /** Address styling not present in IE 8/9, Safari 5, and Chrome. */ |
| abbr[title] { border-bottom: 1px dotted; } |
| |
| /** Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. */ |
| b, strong { font-weight: bold; } |
| |
| /** Address styling not present in Safari 5 and Chrome. */ |
| dfn { font-style: italic; } |
| |
| /** Address differences between Firefox and other browsers. */ |
| hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0; } |
| |
| /** Address styling not present in IE 8/9. */ |
| mark { background: #ff0; color: #000; } |
| |
| /** Correct font family set oddly in Safari 5 and Chrome. */ |
| code, kbd, pre, samp { font-family: monospace, serif; font-size: 1em; } |
| |
| /** Improve readability of pre-formatted text in all browsers. */ |
| pre { white-space: pre-wrap; } |
| |
| /** Set consistent quote types. */ |
| q { quotes: "\201C" "\201D" "\2018" "\2019"; } |
| |
| /** Address inconsistent and variable font size in all browsers. */ |
| small { font-size: 80%; } |
| |
| /** Prevent `sub` and `sup` affecting `line-height` in all browsers. */ |
| sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } |
| |
| sup { top: -0.5em; } |
| |
| sub { bottom: -0.25em; } |
| |
| /* ========================================================================== Embedded content ========================================================================== */ |
| /** Remove border when inside `a` element in IE 8/9. */ |
| img { border: 0; } |
| |
| /** Correct overflow displayed oddly in IE 9. */ |
| svg:not(:root) { overflow: hidden; } |
| |
| /* ========================================================================== Figures ========================================================================== */ |
| /** Address margin not present in IE 8/9 and Safari 5. */ |
| figure { margin: 0; } |
| |
| /* ========================================================================== Forms ========================================================================== */ |
| /** Define consistent border, margin, and padding. */ |
| fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; } |
| |
| /** 1. Correct `color` not being inherited in IE 8/9. 2. Remove padding so people aren't caught out if they zero out fieldsets. */ |
| legend { border: 0; /* 1 */ padding: 0; /* 2 */ } |
| |
| /** 1. Correct font family not being inherited in all browsers. 2. Correct font size not being inherited in all browsers. 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. */ |
| button, input, select, textarea { font-family: inherit; /* 1 */ font-size: 100%; /* 2 */ margin: 0; /* 3 */ } |
| |
| /** Address Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet. */ |
| button, input { line-height: normal; } |
| |
| /** Address inconsistent `text-transform` inheritance for `button` and `select`. All other form control elements do not inherit `text-transform` values. Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. Correct `select` style inheritance in Firefox 4+ and Opera. */ |
| button, select { text-transform: none; } |
| |
| /** 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls. 2. Correct inability to style clickable `input` types in iOS. 3. Improve usability and consistency of cursor style between image-type `input` and others. */ |
| button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ } |
| |
| /** Re-set default cursor for disabled elements. */ |
| button[disabled], html input[disabled] { cursor: default; } |
| |
| /** 1. Address box sizing set to `content-box` in IE 8/9. 2. Remove excess padding in IE 8/9. */ |
| input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ } |
| |
| /** 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome (include `-moz` to future-proof). */ |
| input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box; } |
| |
| /** Remove inner padding and search cancel button in Safari 5 and Chrome on OS X. */ |
| input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } |
| |
| /** Remove inner padding and border in Firefox 4+. */ |
| button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } |
| |
| /** 1. Remove default vertical scrollbar in IE 8/9. 2. Improve readability and alignment in all browsers. */ |
| textarea { overflow: auto; /* 1 */ vertical-align: top; /* 2 */ } |
| |
| /* ========================================================================== Tables ========================================================================== */ |
| /** Remove most spacing between table cells. */ |
| table { border-collapse: collapse; border-spacing: 0; } |
| |
| meta.foundation-mq-small { font-family: "only screen and (min-width: 768px)"; width: 768px; } |
| |
| meta.foundation-mq-medium { font-family: "only screen and (min-width:1280px)"; width: 1280px; } |
| |
| meta.foundation-mq-large { font-family: "only screen and (min-width:1440px)"; width: 1440px; } |
| |
| *, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } |
| |
| html, body { font-size: 100%; } |
| |
| body { background: white; color: #222222; padding: 0; margin: 0; font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; font-weight: normal; font-style: normal; line-height: 1; position: relative; cursor: auto; } |
| |
| a:hover { cursor: pointer; } |
| |
| img, object, embed { max-width: 100%; height: auto; } |
| |
| object, embed { height: 100%; } |
| |
| img { -ms-interpolation-mode: bicubic; } |
| |
| #map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object { max-width: none !important; } |
| |
| .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; } |
| |
| .antialiased { -webkit-font-smoothing: antialiased; } |
| |
| img { display: inline-block; vertical-align: middle; } |
| |
| textarea { height: auto; min-height: 50px; } |
| |
| select { width: 100%; } |
| |
| object, svg { display: inline-block; vertical-align: middle; } |
| |
| .center { margin-left: auto; margin-right: auto; } |
| |
| .spread { width: 100%; } |
| |
| p.lead, .paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { font-size: 1.21875em; line-height: 1.6; } |
| |
| .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.4; color: black; font-weight: 300; margin-top: 0.2em; margin-bottom: 0.5em; } |
| |
| /* Typography resets */ |
| 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; } |
| |
| /* Default Link Styles */ |
| a { color: #0068b0; text-decoration: none; line-height: inherit; } |
| a:hover, a:focus { color: #333333; } |
| a img { border: none; } |
| |
| /* Default paragraph styles */ |
| p { font-family: Noto, sans-serif; font-weight: normal; font-size: 1em; line-height: 1.6; margin-bottom: 0.75em; text-rendering: optimizeLegibility; } |
| p aside { font-size: 0.875em; line-height: 1.35; font-style: italic; } |
| |
| /* Default header styles */ |
| h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { font-family: Noto, sans-serif; font-weight: normal; font-style: normal; color: black; text-rendering: optimizeLegibility; margin-top: 0.5em; margin-bottom: 0.5em; line-height: 1.2125em; } |
| h1 small, h2 small, h3 small, #toctitle small, .sidebarblock > .content > .title small, h4 small, h5 small, h6 small { font-size: 60%; color: #4d4d4d; line-height: 0; } |
| |
| h1 { font-size: 2.125em; } |
| |
| h2 { font-size: 1.6875em; } |
| |
| h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.375em; } |
| |
| h4 { font-size: 1.125em; } |
| |
| h5 { font-size: 1.125em; } |
| |
| h6 { font-size: 1em; } |
| |
| hr { border: solid #dddddd; border-width: 1px 0 0; clear: both; margin: 1.25em 0 1.1875em; height: 0; } |
| |
| /* Helpful Typography Defaults */ |
| 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: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; color: #264357; } |
| |
| /* Lists */ |
| ul, ol, dl { font-size: 1em; line-height: 1.6; margin-bottom: 0.75em; list-style-position: outside; font-family: Noto, sans-serif; } |
| |
| ul, ol { margin-left: 1.5em; } |
| ul.no-bullet, ol.no-bullet { margin-left: 1.5em; } |
| |
| /* Unordered Lists */ |
| ul li ul, ul li ol { margin-left: 1.25em; margin-bottom: 0; font-size: 1em; /* Override nested font-size change */ } |
| 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; } |
| ul.no-bullet { list-style: none; } |
| |
| /* Ordered Lists */ |
| ol li ul, ol li ol { margin-left: 1.25em; margin-bottom: 0; } |
| |
| /* Definition Lists */ |
| dl dt { margin-bottom: 0.3em; font-weight: bold; } |
| dl dd { margin-bottom: 0.75em; } |
| |
| /* Abbreviations */ |
| abbr, acronym { text-transform: uppercase; font-size: 90%; color: black; border-bottom: 1px dotted #dddddd; cursor: help; } |
| |
| abbr { text-transform: none; } |
| |
| /* Blockquotes */ |
| blockquote { margin: 0 0 0.75em; padding: 0.5625em 1.25em 0 1.1875em; border-left: 1px solid #dddddd; } |
| blockquote cite { display: block; font-size: 0.8125em; color: #5e93b8; } |
| blockquote cite:before { content: "\2014 \0020"; } |
| blockquote cite a, blockquote cite a:visited { color: #5e93b8; } |
| |
| blockquote, blockquote p { line-height: 1.6; color: #333333; } |
| |
| /* Microformats */ |
| .vcard { display: inline-block; margin: 0 0 1.25em 0; border: 1px solid #dddddd; padding: 0.625em 0.75em; } |
| .vcard li { margin: 0; display: block; } |
| .vcard .fn { font-weight: bold; font-size: 0.9375em; } |
| |
| .vevent .summary { font-weight: bold; } |
| .vevent abbr { cursor: auto; text-decoration: none; font-weight: bold; border: none; padding: 0 0.0625em; } |
| |
| @media only screen and (min-width: 768px) { h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; } |
| h1 { font-size: 2.75em; } |
| h2 { font-size: 2.3125em; } |
| h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.6875em; } |
| h4 { font-size: 1.4375em; } } |
| /* Tables */ |
| table { background: white; margin-bottom: 1.25em; border: solid 1px #d8d8ce; } |
| table thead, table tfoot { background: -webkit-linear-gradient(top, #add386, #90b66a); font-weight: bold; } |
| table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td { padding: 0.5em 0.625em 0.625em; font-size: inherit; color: white; text-align: left; } |
| table tr th, table tr td { padding: 0.5625em 0.625em; font-size: inherit; color: #6d6e71; } |
| table tr.even, table tr.alt, table tr:nth-of-type(even) { background: #edf2f2; } |
| 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.4; } |
| |
| body { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; tab-size: 4; } |
| |
| h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; } |
| |
| a:hover, a:focus { text-decoration: underline; } |
| |
| .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: inherit; font-style: normal !important; letter-spacing: 0; padding: 0; background-color: white; -webkit-border-radius: 0; border-radius: 0; line-height: inherit; word-wrap: break-word; } |
| *:not(pre) > code.nobreak { word-wrap: normal; } |
| *:not(pre) > code.nowrap { white-space: nowrap; } |
| |
| pre, pre > code { line-height: 1.6; color: #264357; font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; } |
| |
| em em { font-style: normal; } |
| |
| strong strong { font-weight: normal; } |
| |
| .keyseq { color: #333333; } |
| |
| kbd { font-family: Consolas, "Liberation Mono", Courier, monospace; display: inline-block; color: black; font-size: 0.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, 0.2), 0 0 0 0.1em white inset; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; margin: 0 0.15em; padding: 0.2em 0.5em; vertical-align: middle; position: relative; top: -0.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: -0.02em; } |
| .menuseq b.caret { font-size: 1.25em; line-height: 0.8; } |
| .menuseq i.caret { font-weight: bold; text-align: center; width: 0.45em; } |
| |
| b.button:before, b.button:after { position: relative; top: -1px; font-weight: normal; } |
| |
| b.button:before { content: "["; padding: 0 3px 0 2px; } |
| |
| b.button:after { content: "]"; padding: 0 2px 0 3px; } |
| |
| #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: 1.5em; padding-right: 1.5em; } |
| #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: black; margin-top: 2.25rem; margin-bottom: 0; } |
| #header > h1:first-child + #toc { margin-top: 8px; border-top: 1px solid #dddddd; } |
| #header > h1:only-child, body.toc2 #header > h1:nth-last-child(2) { border-bottom: 1px solid #dddddd; padding-bottom: 8px; } |
| #header .details { border-bottom: 1px solid #dddddd; line-height: 1.45; padding-top: 0.25em; padding-bottom: 0.25em; padding-left: 0.25em; color: #5e93b8; 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: -0.125em; } |
| #header .details span.email a { color: #333333; } |
| #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: #333333; } |
| #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: black; border-bottom: 1px solid #dddddd; padding-bottom: 8px; margin-top: 0; padding-top: 1rem; margin-bottom: 1.25rem; } |
| |
| #toc { border-bottom: 0 solid #dddddd; padding-bottom: 0.5em; } |
| #toc > ul { margin-left: 0.125em; } |
| #toc ul.sectlevel0 > li > a { font-style: italic; } |
| #toc ul.sectlevel0 ul.sectlevel1 { margin: 0.5em 0; } |
| #toc ul { font-family: Noto, sans-serif; list-style-type: none; } |
| #toc li { line-height: 1.3334; margin-top: 0.3334em; } |
| #toc a { text-decoration: none; } |
| #toc a:active { text-decoration: underline; } |
| |
| #toctitle { color: black; font-size: 1.2em; } |
| |
| @media only 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: white; position: fixed; width: 15em; left: 0; top: 0; border-right: 1px solid #dddddd; 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: 0.8rem; font-size: 1.2em; } |
| #toc.toc2 > ul { font-size: 0.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: 0.5em; margin-bottom: 0.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 #dddddd; left: auto; right: 0; } } |
| @media only 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: 0.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: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; } |
| #content #toc > :first-child { margin-top: 0; } |
| #content #toc > :last-child { margin-bottom: 0; } |
| |
| #footer { max-width: 100%; background-color: none; padding: 1.25em; } |
| |
| #footer-text { color: black; line-height: 1.44; } |
| |
| #content { margin-bottom: 0.625em; } |
| |
| .sect1 { padding-bottom: 0.625em; } |
| |
| @media only 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: 0 solid #dddddd; } |
| |
| #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: normal; } |
| #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: 0.85em; display: block; padding-top: 0.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: black; 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: black; } |
| |
| .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; } |
| |
| table.tableblock > caption.title { white-space: nowrap; overflow: visible; max-width: 0; } |
| |
| .paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { color: black; } |
| |
| table.tableblock #preamble > .sectionbody > .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: initial; } |
| .admonitionblock > table td.icon .title { font-weight: bold; font-family: Noto, sans-serif; text-transform: uppercase; } |
| .admonitionblock > table td.content { padding-left: 1.125em; padding-right: 1.25em; border-left: 1px solid #dddddd; color: #5e93b8; } |
| .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: white; -webkit-border-radius: 0; border-radius: 0; } |
| .exampleblock > .content > :first-child { margin-top: 0; } |
| .exampleblock > .content > :last-child { margin-bottom: 0; } |
| |
| .sidebarblock { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; } |
| .sidebarblock > :first-child { margin-top: 0; } |
| .sidebarblock > :last-child { margin-bottom: 0; } |
| .sidebarblock > .content > .title { color: black; margin-top: 0; } |
| |
| .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: #eeeeee; } |
| .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] { border: 1px hidden #666666; -webkit-border-radius: 0; border-radius: 0; word-wrap: break-word; padding: 1.25em 1.5625em 1.125em 1.5625em; font-size: 0.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 only screen and (min-width: 768px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 0.90625em; } } |
| @media only screen and (min-width: 1280px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 1em; } } |
| |
| .literalblock.output pre { color: #eeeeee; background-color: #264357; } |
| |
| .listingblock pre.highlightjs { padding: 0; } |
| .listingblock pre.highlightjs > code { padding: 1.25em 1.5625em 1.125em 1.5625em; -webkit-border-radius: 0; border-radius: 0; } |
| |
| .listingblock > .content { position: relative; } |
| |
| .listingblock code[data-lang]:before { display: none; content: attr(data-lang); position: absolute; font-size: 0.75em; top: 0.425rem; right: 0.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: 0.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.6; } |
| |
| 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 #dddddd; } |
| |
| pre.pygments .lineno { display: inline-block; margin-right: .25em; } |
| |
| table.pyhltable .linenodiv { background: none !important; padding-right: 0 !important; } |
| |
| .quoteblock { margin: 0 1em 0.75em 1.5em; display: table; } |
| .quoteblock > .title { margin-left: -1.5em; margin-bottom: 0.75em; } |
| .quoteblock blockquote, .quoteblock blockquote p { color: #333333; font-size: 1.15rem; line-height: 1.75; word-spacing: 0.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: 0.6em; margin-left: -0.6em; color: black; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); } |
| .quoteblock blockquote > .paragraph:last-child p { margin-bottom: 0; } |
| .quoteblock .attribution { margin-top: 0.5em; margin-right: 0.5ex; text-align: right; } |
| .quoteblock .quoteblock { margin-left: 0; margin-right: 0; padding: 0.5em 0; border-left: 3px solid #5e93b8; } |
| .quoteblock .quoteblock blockquote { padding: 0 0 0 0.75em; } |
| .quoteblock .quoteblock blockquote:before { display: none; } |
| |
| .verseblock { margin: 0 1em 0.75em 1em; } |
| .verseblock pre { font-family: "Open Sans", "DejaVu Sans", sans; font-size: 1.15rem; color: #333333; font-weight: 300; text-rendering: optimizeLegibility; } |
| .verseblock pre strong { font-weight: 400; } |
| .verseblock .attribution { margin-top: 1.25rem; margin-left: 0.5ex; } |
| |
| .quoteblock .attribution, .verseblock .attribution { font-size: 0.8125em; 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: -0.025em; color: #5e93b8; } |
| |
| .quoteblock.abstract { margin: 0 0 0.75em 0; display: block; } |
| .quoteblock.abstract blockquote, .quoteblock.abstract blockquote p { text-align: left; word-spacing: 0; } |
| .quoteblock.abstract blockquote:before, .quoteblock.abstract blockquote p:first-of-type:before { display: none; } |
| |
| table.tableblock { max-width: 100%; border-collapse: separate; } |
| table.tableblock td > .paragraph:last-child p > p:last-child, table.tableblock th > p:last-child, table.tableblock td > p:last-child { margin-bottom: 0; } |
| |
| table.tableblock, th.tableblock, td.tableblock { border: 0 solid #d8d8ce; } |
| |
| 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 0; } |
| |
| table.grid-rows > tfoot > tr > .tableblock { border-width: 1px 0 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 { border-width: 1px 0; } |
| |
| 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.4; background: -webkit-linear-gradient(top, #add386, #90b66a); } |
| |
| tbody tr th, tbody tr th p, tfoot tr th, tfoot tr th p { color: white; 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: 0.375em; } |
| |
| 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: 0.625em; } |
| |
| ul.unstyled, ol.unstyled { margin-left: 0; } |
| |
| ul.checklist { margin-left: 0.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: 0.8em; position: relative; bottom: 0.125em; } |
| |
| ul.checklist li > p:first-child > input[type="checkbox"]:first-child { margin-right: 0.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 0.375em -0.75em; } |
| |
| ul.inline > li { margin-left: 0.75em; } |
| |
| .unstyled dl dt { font-weight: normal; 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 0.625em; } |
| |
| td.hdlist1 { font-weight: bold; padding-bottom: 0.75em; } |
| |
| .literalblock + .colist, .listingblock + .colist { margin-top: -0.5em; } |
| |
| .colist > table tr > td:first-of-type { padding: 0.4em 0.75em 0 0.75em; line-height: 1; vertical-align: top; } |
| .colist > table tr > td:first-of-type img { max-width: initial; } |
| .colist > table tr > td:last-of-type { padding: 0.25em 0; } |
| |
| .thumb, .th { line-height: 0; display: inline-block; border: solid 4px white; -webkit-box-shadow: 0 0 0 1px #dddddd; box-shadow: 0 0 0 1px #dddddd; } |
| |
| .imageblock.left, .imageblock[style*="float: left"] { margin: 0.25em 0.625em 1.25em 0; } |
| .imageblock.right, .imageblock[style*="float: right"] { margin: 0.25em 0 1.25em 0.625em; } |
| .imageblock > .title { margin-bottom: 0; } |
| .imageblock.thumb, .imageblock.th { border-width: 6px; } |
| .imageblock.thumb > .title, .imageblock.th > .title { padding: 0 0.125em; } |
| |
| .image.left, .image.right { margin-top: 0.25em; margin-bottom: 0.25em; display: inline-block; line-height: 0; } |
| .image.left { margin-right: 0.625em; } |
| .image.right { margin-left: 0.625em; } |
| |
| a.image { text-decoration: none; display: inline-block; } |
| a.image object { pointer-events: none; } |
| |
| sup.footnote, sup.footnoteref { font-size: 0.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: 0.75em; padding-bottom: 0.75em; margin-bottom: 0.625em; } |
| #footnotes hr { width: 20%; min-width: 6.25em; margin: -0.25em 0 0.75em 0; border-width: 1px 0 0 0; } |
| #footnotes .footnote { padding: 0 0.375em 0 0.225em; line-height: 1.3334; font-size: 0.875em; margin-left: 1.2em; margin-bottom: 0.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: -0.625em; margin-bottom: 0; padding: 0.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: black; } |
| |
| .black-background { background-color: black; } |
| |
| .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, 0.5); cursor: default; } |
| .admonitionblock td.icon .icon-note:before { content: "\f05a"; color: #29475c; } |
| .admonitionblock td.icon .icon-tip:before { content: "\f0eb"; text-shadow: 1px 1px 2px rgba(155, 155, 0, 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: black; -webkit-border-radius: 100px; border-radius: 100px; text-align: center; font-size: 0.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: -0.125em; } |
| |
| b.conum * { color: inherit !important; } |
| |
| .conum:not([data-value]):empty { display: none; } |
| |
| h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { border-bottom: 1px solid #dddddd; } |
| |
| .sect1 { padding-bottom: 0; } |
| |
| #toctitle { color: #00406F; font-weight: normal; margin-top: 1.5em; } |
| |
| .sidebarblock { border-color: #aaa; } |
| |
| code { -webkit-border-radius: 4px; border-radius: 4px; } |
| |
| p.tableblock.header { color: #6d6e71; } |
| |
| .literalblock pre, .listingblock pre { background: #eeeeee; } |
| |
| </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 OpenCL<sup>™</sup> Specification</h1> |
| <div class="details"> |
| <span id="author" class="author">Khronos<sup>®</sup> OpenCL Working Group</span><br> |
| <span id="revnumber">version v2.2-10,</span> |
| <span id="revdate">Tue, 05 Feb 2019 21:16:07 +0000</span> |
| <br><span id="revremark">from git branch: commit: 00422daf5dc013f21ab633479577c7cc225150e2</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="#_normative_references">1.1. Normative References</a></li> |
| <li><a href="#_version_numbers">1.2. Version Numbers</a></li> |
| </ul> |
| </li> |
| <li><a href="#_glossary">2. Glossary</a></li> |
| <li><a href="#_the_opencl_architecture">3. The OpenCL Architecture</a> |
| <ul class="sectlevel2"> |
| <li><a href="#_platform_model">3.1. Platform Model</a></li> |
| <li><a href="#_execution_model">3.2. Execution Model</a></li> |
| <li><a href="#_memory_model">3.3. Memory Model</a></li> |
| <li><a href="#opencl-framework">3.4. The OpenCL Framework</a></li> |
| </ul> |
| </li> |
| <li><a href="#opencl-platform-layer">4. The OpenCL Platform Layer</a> |
| <ul class="sectlevel2"> |
| <li><a href="#_querying_platform_info">4.1. Querying Platform Info</a></li> |
| <li><a href="#platform-querying-devices">4.2. Querying Devices</a></li> |
| <li><a href="#_partitioning_a_device">4.3. Partitioning a Device</a></li> |
| <li><a href="#_contexts">4.4. Contexts</a></li> |
| </ul> |
| </li> |
| <li><a href="#opencl-runtime">5. The OpenCL Runtime</a> |
| <ul class="sectlevel2"> |
| <li><a href="#_command_queues">5.1. Command Queues</a></li> |
| <li><a href="#_buffer_objects">5.2. Buffer Objects</a></li> |
| <li><a href="#_image_objects">5.3. Image Objects</a></li> |
| <li><a href="#_pipes">5.4. Pipes</a></li> |
| <li><a href="#_querying_unmapping_migrating_retaining_and_releasing_memory_objects">5.5. Querying, Unmapping, Migrating, Retaining and Releasing Memory Objects</a></li> |
| <li><a href="#_shared_virtual_memory">5.6. Shared Virtual Memory</a></li> |
| <li><a href="#_sampler_objects">5.7. Sampler Objects</a></li> |
| <li><a href="#_program_objects">5.8. Program Objects</a></li> |
| <li><a href="#_kernel_objects">5.9. Kernel Objects</a></li> |
| <li><a href="#_executing_kernels">5.10. Executing Kernels</a></li> |
| <li><a href="#event-objects">5.11. Event Objects</a></li> |
| <li><a href="#markers-barriers-waiting-for-events">5.12. Markers, Barriers and Waiting for Events</a></li> |
| <li><a href="#_out_of_order_execution_of_kernels_and_memory_object_commands">5.13. Out-of-order Execution of Kernels and Memory Object Commands</a></li> |
| <li><a href="#profiling-operations">5.14. Profiling Operations on Memory Objects and Kernels</a></li> |
| <li><a href="#_flush_and_finish">5.15. Flush and Finish</a></li> |
| </ul> |
| </li> |
| <li><a href="#_associated_opencl_specification">6. Associated OpenCL specification</a> |
| <ul class="sectlevel2"> |
| <li><a href="#spirv-il">6.1. SPIR-V Intermediate language</a></li> |
| <li><a href="#opencl-extensions">6.2. Extensions to OpenCL</a></li> |
| <li><a href="#_support_for_earlier_opencl_c_kernel_languages">6.3. Support for earlier OpenCL C kernel languages</a></li> |
| </ul> |
| </li> |
| <li><a href="#opencl-embedded-profile">7. OpenCL Embedded Profile</a></li> |
| <li><a href="#_shared_objects_thread_safety">Appendix A: Shared Objects, Thread Safety</a> |
| <ul class="sectlevel2"> |
| <li><a href="#shared-opencl-objects">Shared OpenCL Objects</a></li> |
| <li><a href="#_multiple_host_threads">Multiple Host Threads</a></li> |
| </ul> |
| </li> |
| <li><a href="#_portability">Appendix B: Portability</a></li> |
| <li><a href="#data-types">Appendix C: Application Data Types</a> |
| <ul class="sectlevel2"> |
| <li><a href="#scalar-data-types">Shared Application Scalar Data Types</a></li> |
| <li><a href="#vector-data-types">Supported Application Vector Data Types</a></li> |
| <li><a href="#alignment-app-data-types">Alignment of Application Data Types</a></li> |
| <li><a href="#_vector_literals">Vector Literals</a></li> |
| <li><a href="#vector-components">Vector Components</a></li> |
| <li><a href="#_implicit_conversions">Implicit Conversions</a></li> |
| <li><a href="#_explicit_casts">Explicit Casts</a></li> |
| <li><a href="#_other_operators_and_functions">Other operators and functions</a></li> |
| <li><a href="#_application_constant_definitions">Application constant definitions</a></li> |
| </ul> |
| </li> |
| <li><a href="#check-copy-overlap">Appendix D: CL_MEM_COPY_OVERLAP</a></li> |
| <li><a href="#_changes">Appendix E: Changes</a> |
| <ul class="sectlevel2"> |
| <li><a href="#_summary_of_changes_from_opencl_1_0">Summary of changes from OpenCL 1.0</a></li> |
| <li><a href="#_summary_of_changes_from_opencl_1_1">Summary of changes from OpenCL 1.1</a></li> |
| <li><a href="#_summary_of_changes_from_opencl_1_2">Summary of changes from OpenCL 1.2</a></li> |
| <li><a href="#_summary_of_changes_from_opencl_2_0">Summary of changes from OpenCL 2.0</a></li> |
| <li><a href="#_summary_of_changes_from_opencl_2_1">Summary of changes from OpenCL 2.1</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-2019 The Khronos Group.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This specification is protected by copyright laws and contains material proprietary |
| to the Khronos Group, Inc. Except as described by these terms, 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.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Khronos Group grants a conditional copyright license to use and reproduce the |
| unmodified specification for any purpose, without fee or royalty, EXCEPT no licenses |
| to any patent, trademark or other intellectual property rights are granted under |
| these terms. Parties desiring to implement the specification and make use of |
| Khronos trademarks in relation to that implementation, and receive reciprocal patent |
| license protection under the Khronos IP Policy must become Adopters and confirm the |
| implementation as conformant under the process defined by Khronos for this |
| specification; see <a href="https://www.khronos.org/adopters" class="bare">https://www.khronos.org/adopters</a>.</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: |
| merchantability, fitness for a particular purpose, non-infringement of any |
| intellectual property, correctness, accuracy, completeness, timeliness, and |
| reliability. 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>Vulkan and Khronos are registered trademarks, and OpenXR, SPIR, SPIR-V, SYCL, WebGL, |
| WebCL, OpenVX, OpenVG, EGL, COLLADA, glTF, NNEF, OpenKODE, OpenKCAM, StreamInput, |
| OpenWF, OpenSL ES, OpenMAX, OpenMAX AL, OpenMAX IL, OpenMAX DL, OpenML and DevU are |
| trademarks of the Khronos Group Inc. ASTC is a trademark of ARM Holdings PLC, |
| 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> |
| <div class="paragraph"> |
| <p><strong>Acknowledgements</strong></p> |
| </div> |
| <div class="paragraph"> |
| <p>The OpenCL specification is the result of the contributions of many people, |
| representing a cross section of the desktop, hand-held, and embedded |
| computer industry. |
| Following is a partial list of the contributors, including the company that |
| they represented at the time of their contribution:</p> |
| </div> |
| <div class="paragraph"> |
| <p>Chuck Rose, Adobe<br> |
| Eric Berdahl, Adobe<br> |
| Shivani Gupta, Adobe<br> |
| Bill Licea Kane, AMD<br> |
| Ed Buckingham, AMD<br> |
| Jan Civlin, AMD<br> |
| Laurent Morichetti, AMD<br> |
| Mark Fowler, AMD<br> |
| Marty Johnson, AMD<br> |
| Michael Mantor, AMD<br> |
| Norm Rubin, AMD<br> |
| Ofer Rosenberg, AMD<br> |
| Brian Sumner, AMD<br> |
| Victor Odintsov, AMD<br> |
| Aaftab Munshi, Apple<br> |
| Abe Stephens, Apple<br> |
| Alexandre Namaan, Apple<br> |
| Anna Tikhonova, Apple<br> |
| Chendi Zhang, Apple<br> |
| Eric Bainville, Apple<br> |
| David Hayward, Apple<br> |
| Giridhar Murthy, Apple<br> |
| Ian Ollmann, Apple<br> |
| Inam Rahman, Apple<br> |
| James Shearer, Apple<br> |
| MonPing Wang, Apple<br> |
| Tanya Lattner, Apple<br> |
| Mikael Bourges-Sevenier, Aptina<br> |
| Anton Lokhmotov, ARM<br> |
| Dave Shreiner, ARM<br> |
| Hedley Francis, ARM<br> |
| Robert Elliott, ARM<br> |
| Scott Moyers, ARM<br> |
| Tom Olson, ARM<br> |
| Anastasia Stulova, ARM<br> |
| Christopher Thompson-Walsh, Broadcom<br> |
| Holger Waechtler, Broadcom<br> |
| Norman Rink, Broadcom<br> |
| Andrew Richards, Codeplay<br> |
| Maria Rovatsou, Codeplay<br> |
| Alistair Donaldson, Codeplay<br> |
| Alastair Murray, Codeplay<br> |
| Stephen Frye, Electronic Arts<br> |
| Eric Schenk, Electronic Arts<br> |
| Daniel Laroche, Freescale<br> |
| David Neto, Google<br> |
| Robin Grosman, Huawei<br> |
| Craig Davies, Huawei<br> |
| Brian Horton, IBM<br> |
| Brian Watt, IBM<br> |
| Gordon Fossum, IBM<br> |
| Greg Bellows, IBM<br> |
| Joaquin Madruga, IBM<br> |
| Mark Nutter, IBM<br> |
| Mike Perks, IBM<br> |
| Sean Wagner, IBM<br> |
| Jon Parr, Imagination Technologies<br> |
| Robert Quill, Imagination Technologies<br> |
| James McCarthy, Imagination Technologie<br> |
| Jon Leech, Independent<br> |
| Aaron Kunze, Intel<br> |
| Aaron Lefohn, Intel<br> |
| Adam Lake, Intel<br> |
| Alexey Bader, Intel<br> |
| Allen Hux, Intel<br> |
| Andrew Brownsword, Intel<br> |
| Andrew Lauritzen, Intel<br> |
| Bartosz Sochacki, Intel<br> |
| Ben Ashbaugh, Intel<br> |
| Brian Lewis, Intel<br> |
| Geoff Berry, Intel<br> |
| Hong Jiang, Intel<br> |
| Jayanth Rao, Intel<br> |
| Josh Fryman, Intel<br> |
| Larry Seiler, Intel<br> |
| Mike MacPherson, Intel<br> |
| Murali Sundaresan, Intel<br> |
| Paul Lalonde, Intel<br> |
| Raun Krisch, Intel<br> |
| Stephen Junkins, Intel<br> |
| Tim Foley, Intel<br> |
| Timothy Mattson, Intel<br> |
| Yariv Aridor, Intel<br> |
| Michael Kinsner, Intel<br> |
| Kevin Stevens, Intel<br> |
| Benjamin Bergen, Los Alamos National Laboratory<br> |
| Roy Ju, Mediatek<br> |
| Bor-Sung Liang, Mediatek<br> |
| Rahul Agarwal, Mediatek<br> |
| Michal Witaszek, Mobica<br> |
| JenqKuen Lee, NTHU<br> |
| Amit Rao, NVIDIA<br> |
| Ashish Srivastava, NVIDIA<br> |
| Bastiaan Aarts, NVIDIA<br> |
| Chris Cameron, NVIDIA<br> |
| Christopher Lamb, NVIDIA<br> |
| Dibyapran Sanyal, NVIDIA<br> |
| Guatam Chakrabarti, NVIDIA<br> |
| Ian Buck, NVIDIA<br> |
| Jaydeep Marathe, NVIDIA<br> |
| Jian-Zhong Wang, NVIDIA<br> |
| Karthik Raghavan Ravi, NVIDIA<br> |
| Kedar Patil, NVIDIA<br> |
| Manjunath Kudlur, NVIDIA<br> |
| Mark Harris, NVIDIA<br> |
| Michael Gold, NVIDIA<br> |
| Neil Trevett, NVIDIA<br> |
| Richard Johnson, NVIDIA<br> |
| Sean Lee, NVIDIA<br> |
| Tushar Kashalikar, NVIDIA<br> |
| Vinod Grover, NVIDIA<br> |
| Xiangyun Kong, NVIDIA<br> |
| Yogesh Kini, NVIDIA<br> |
| Yuan Lin, NVIDIA<br> |
| Mayuresh Pise, NVIDIA<br> |
| Allan Tzeng, QUALCOMM<br> |
| Alex Bourd, QUALCOMM<br> |
| Anirudh Acharya, QUALCOMM<br> |
| Andrew Gruber, QUALCOMM<br> |
| Andrzej Mamona, QUALCOMM<br> |
| Benedict Gaster, QUALCOMM<br> |
| Bill Torzewski, QUALCOMM<br> |
| Bob Rychlik, QUALCOMM<br> |
| Chihong Zhang, QUALCOMM<br> |
| Chris Mei, QUALCOMM<br> |
| Colin Sharp, QUALCOMM<br> |
| David Garcia, QUALCOMM<br> |
| David Ligon, QUALCOMM<br> |
| Jay Yun, QUALCOMM<br> |
| Lee Howes, QUALCOMM<br> |
| Richard Ruigrok, QUALCOMM<br> |
| Robert J. Simpson, QUALCOMM<br> |
| Sumesh Udayakumaran, QUALCOMM<br> |
| Vineet Goel, QUALCOMM<br> |
| Lihan Bin, QUALCOMM<br> |
| Vlad Shimanskiy, QUALCOMM<br> |
| Jian Liu, QUALCOMM<br> |
| Tasneem Brutch, Samsung<br> |
| Yoonseo Choi, Samsung<br> |
| Dennis Adams, Sony<br> |
| Pr-Anders Aronsson, Sony<br> |
| Jim Rasmusson, Sony<br> |
| Thierry Lepley, STMicroelectronics<br> |
| Anton Gorenko, StreamHPC<br> |
| Jakub Szuppe, StreamHPC<br> |
| Vincent Hindriksen, StreamHPC<br> |
| Alan Ward, Texas Instruments<br> |
| Yuan Zhao, Texas Instruments<br> |
| Pete Curry, Texas Instruments<br> |
| Simon McIntosh-Smith, University of Bristol<br> |
| James Price, University of Bristol<br> |
| Paul Preney, University of Windsor<br> |
| Shane Peelar, University of Windsor<br> |
| Brian Hutsell, Vivante<br> |
| Mike Cai, Vivante<br> |
| Sumeet Kumar, Vivante<br> |
| Wei-Lun Kao, Vivante<br> |
| Xing Wang, Vivante<br> |
| Jeff Fifield, Xilinx<br> |
| Hem C. Neema, Xilinx<br> |
| Henry Styles, Xilinx<br> |
| Ralph Wittig, Xilinx<br> |
| Ronan Keryell, Xilinx<br> |
| AJ Guillon, YetiWare Inc<br></p> |
| </div> |
| <div style="page-break-after: always;"></div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_introduction">1. Introduction</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>Modern processor architectures have embraced parallelism as an important |
| pathway to increased performance. |
| Facing technical challenges with higher clock speeds in a fixed power |
| envelope, Central Processing Units (CPUs) now improve performance by adding |
| multiple cores. |
| Graphics Processing Units (GPUs) have also evolved from fixed function |
| rendering devices into programmable parallel processors. |
| As todays computer systems often include highly parallel CPUs, GPUs and |
| other types of processors, it is important to enable software developers to |
| take full advantage of these heterogeneous processing platforms.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Creating applications for heterogeneous parallel processing platforms is |
| challenging as traditional programming approaches for multi-core CPUs and |
| GPUs are very different. |
| CPU-based parallel programming models are typically based on standards but |
| usually assume a shared address space and do not encompass vector |
| operations. |
| General purpose GPU programming models address complex memory hierarchies |
| and vector operations but are traditionally platform-, vendor- or |
| hardware-specific. |
| These limitations make it difficult for a developer to access the compute |
| power of heterogeneous CPUs, GPUs and other types of processors from a |
| single, multi-platform source code base. |
| More than ever, there is a need to enable software developers to effectively |
| take full advantage of heterogeneous processing platforms from high |
| performance compute servers, through desktop computer systems to handheld |
| devices - that include a diverse mix of parallel CPUs, GPUs and other |
| processors such as DSPs and the Cell/B.E. |
| processor.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>OpenCL</strong> (Open Computing Language) is an open royalty-free standard for |
| general purpose parallel programming across CPUs, GPUs and other processors, |
| giving software developers portable and efficient access to the power of |
| these heterogeneous processing platforms.</p> |
| </div> |
| <div class="paragraph"> |
| <p>OpenCL supports a wide range of applications, ranging from embedded and |
| consumer software to HPC solutions, through a low-level, high-performance, |
| portable abstraction. |
| By creating an efficient, close-to-the-metal programming interface, OpenCL |
| will form the foundation layer of a parallel computing ecosystem of |
| platform-independent tools, middleware and applications. |
| OpenCL is particularly suited to play an increasingly significant role in |
| emerging interactive graphics applications that combine general parallel |
| compute algorithms with graphics rendering pipelines.</p> |
| </div> |
| <div class="paragraph"> |
| <p>OpenCL consists of an API for coordinating parallel computation across |
| heterogeneous processors; and a cross-platform intermediate language with a |
| well-specified computation environment. |
| The OpenCL standard:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Supports both data- and task-based parallel programming models</p> |
| </li> |
| <li> |
| <p>Utilizes a portable and self-contained intermediate representation with |
| support for parallel execution</p> |
| </li> |
| <li> |
| <p>Defines consistent numerical requirements based on IEEE 754</p> |
| </li> |
| <li> |
| <p>Defines a configuration profile for handheld and embedded devices</p> |
| </li> |
| <li> |
| <p>Efficiently interoperates with OpenGL, OpenGL ES and other graphics APIs</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>This document begins with an overview of basic concepts and the architecture |
| of OpenCL, followed by a detailed description of its execution model, memory |
| model and synchronization support. |
| It then discusses the OpenCL platform and runtime API. |
| Some examples are given that describe sample compute use-cases and how they |
| would be written in OpenCL. |
| The specification is divided into a core specification that any OpenCL |
| compliant implementation must support; a handheld/embedded profile which |
| relaxes the OpenCL compliance requirements for handheld and embedded |
| devices; and a set of optional extensions that are likely to move into the |
| core specification in later revisions of the OpenCL specification.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="_normative_references">1.1. Normative References</h3> |
| <div class="paragraph"> |
| <p>Normative references are references to external documents or resources to |
| which implementers of OpenCL must comply with all, or specified portions of, |
| as described in this specification.</p> |
| </div> |
| <div id="iso-c11" class="paragraph"> |
| <p><em>ISO/IEC 9899:2011 - Information technology - Programming languages - C</em>, |
| <a href="https://www.iso.org/standard/57853.html" class="bare">https://www.iso.org/standard/57853.html</a> (final specification), |
| <a href="http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1570.pdf" class="bare">http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1570.pdf</a> (last public |
| draft).</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_version_numbers">1.2. Version Numbers</h3> |
| <div class="paragraph"> |
| <p>The OpenCL version number follows a <em>major.minor-revision</em> scheme. When this |
| version number is used within the API it generally only includes the |
| <em>major.minor</em> components of the version number.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A difference in the <em>major</em> or <em>minor</em> version number indicates that some |
| amount of new functionality has been added to the specification, and may also |
| include behavior changes and bug fixes. |
| Functionality may also be deprecated or removed when the <em>major</em> or <em>minor</em> |
| version changes.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A difference in the <em>revision</em> number indicates small changes to the |
| specification, typically to fix a bug or to clarify language. |
| When the <em>revision</em> number changes there may be an impact on the behavior of |
| existing functionality, but this should not affect backwards compatibility. |
| Functionality should not be added or removed when the <em>revision</em> number |
| changes.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_glossary">2. Glossary</h2> |
| <div class="sectionbody"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">Application </dt> |
| <dd> |
| <p>The combination of the program running on the host and OpenCL devices.</p> |
| </dd> |
| <dt class="hdlist1">Acquire semantics </dt> |
| <dd> |
| <p>One of the memory order semantics defined for synchronization |
| operations. |
| Acquire semantics apply to atomic operations that load from memory. |
| Given two units of execution, <strong>A</strong> and <strong>B</strong>, acting on a shared atomic |
| object <strong>M</strong>, if <strong>A</strong> uses an atomic load of <strong>M</strong> with acquire semantics to |
| synchronize-with an atomic store to <strong>M</strong> by <strong>B</strong> that used release |
| semantics, then <strong>A</strong>'s atomic load will occur before any subsequent |
| operations by <strong>A</strong>. |
| Note that the memory orders <em>release</em>, <em>sequentially consistent</em>, and |
| <em>acquire_release</em> all include <em>release semantics</em> and effectively pair |
| with a load using acquire semantics.</p> |
| </dd> |
| <dt class="hdlist1">Acquire release semantics </dt> |
| <dd> |
| <p>A memory order semantics for synchronization operations (such as atomic |
| operations) that has the properties of both acquire and release memory |
| orders. |
| It is used with read-modify-write operations.</p> |
| </dd> |
| <dt class="hdlist1">Atomic operations </dt> |
| <dd> |
| <p>Operations that at any point, and from any perspective, have either |
| occurred completely, or not at all. |
| Memory orders associated with atomic operations may constrain the |
| visibility of loads and stores with respect to the atomic operations |
| (see <em>relaxed semantics</em>, <em>acquire semantics</em>, <em>release semantics</em> or |
| <em>acquire release semantics</em>).</p> |
| </dd> |
| <dt class="hdlist1">Blocking and Non-Blocking Enqueue API calls </dt> |
| <dd> |
| <p>A <em>non-blocking enqueue API call</em> places a <em>command</em> on a |
| <em>command-queue</em> and returns immediately to the host. |
| The <em>blocking-mode enqueue API calls</em> do not return to the host until |
| the command has completed.</p> |
| </dd> |
| <dt class="hdlist1">Barrier </dt> |
| <dd> |
| <p>There are three types of <em>barriers</em> a command-queue barrier, a |
| work-group barrier and a sub-group barrier.</p> |
| <div class="openblock"> |
| <div class="content"> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>The OpenCL API provides a function to enqueue a <em>command-queue</em> |
| <em>barrier</em> command. |
| This <em>barrier</em> command ensures that all previously enqueued commands to |
| a command-queue have finished execution before any following <em>commands</em> |
| enqueued in the <em>command-queue</em> can begin execution.</p> |
| </li> |
| <li> |
| <p>The OpenCL kernel execution model provides built-in <em>work-group barrier</em> |
| functionality. |
| This <em>barrier</em> built-in function can be used by a <em>kernel</em> executing on |
| a <em>device</em> to perform synchronization between <em>work-items</em> in a |
| <em>work-group</em> executing the <em>kernel</em>. |
| All the <em>work-items</em> of a <em>work-group</em> must execute the <em>barrier</em> |
| construct before any are allowed to continue execution beyond the |
| <em>barrier</em>.</p> |
| </li> |
| <li> |
| <p>The OpenCL kernel execution model provides built-in <em>sub-group barrier</em> |
| functionality. |
| This <em>barrier</em> built-in function can be used by a <em>kernel</em> executing on |
| a <em>device</em> to perform synchronization between <em>work-items</em> in a |
| <em>sub-group</em> executing the <em>kernel</em>. |
| All the <em>work-items</em> of a <em>sub-group</em> must execute the <em>barrier</em> |
| construct before any are allowed to continue execution beyond the |
| <em>barrier</em>.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">Buffer Object </dt> |
| <dd> |
| <p>A memory object that stores a linear collection of bytes. |
| Buffer objects are accessible using a pointer in a <em>kernel</em> executing on |
| a <em>device</em>. |
| Buffer objects can be manipulated by the host using OpenCL API calls. |
| A <em>buffer object</em> encapsulates the following information:</p> |
| <div class="openblock"> |
| <div class="content"> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Size in bytes.</p> |
| </li> |
| <li> |
| <p>Properties that describe usage information and which region to allocate |
| from.</p> |
| </li> |
| <li> |
| <p>Buffer data.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">Built-in Kernel </dt> |
| <dd> |
| <p>A <em>built-in kernel</em> is a <em>kernel</em> that is executed on an OpenCL <em>device</em> |
| or <em>custom device</em> by fixed-function hardware or in firmware. |
| <em>Applications</em> can query the <em>built-in kernels</em> supported by a <em>device</em> |
| or <em>custom device</em>. |
| A <em>program object</em> can only contain <em>kernels</em> written in OpenCL C or |
| <em>built-in kernels</em> but not both. |
| See also <em>Kernel</em> and <em>Program</em>.</p> |
| </dd> |
| <dt class="hdlist1">Child kernel </dt> |
| <dd> |
| <p>See <em>Device-side enqueue</em>.</p> |
| </dd> |
| <dt class="hdlist1">Command </dt> |
| <dd> |
| <p>The OpenCL operations that are submitted to a <em>command-queue</em> for |
| execution. |
| For example, OpenCL commands issue kernels for execution on a compute |
| device, manipulate memory objects, etc.</p> |
| </dd> |
| <dt class="hdlist1">Command-queue </dt> |
| <dd> |
| <p>An object that holds <em>commands</em> that will be executed on a specific |
| <em>device</em>. |
| The <em>command-queue</em> is created on a specific <em>device</em> in a <em>context</em>. |
| <em>Commands</em> to a <em>command-queue</em> are queued in-order but may be executed |
| in-order or out-of-order. |
| <em>Refer to In-order Execution_and_Out-of-order Execution</em>.</p> |
| </dd> |
| <dt class="hdlist1">Command-queue Barrier </dt> |
| <dd> |
| <p>See <em>Barrier</em>.</p> |
| </dd> |
| <dt class="hdlist1">Command synchronization </dt> |
| <dd> |
| <p>Constraints on the order that commands are launched for execution on a |
| device defined in terms of the synchronization points that occur between |
| commands in host command-queues and between commands in device-side |
| command-queues. |
| See <em>synchronization points</em>.</p> |
| </dd> |
| <dt class="hdlist1">Complete </dt> |
| <dd> |
| <p>The final state in the six state model for the execution of a command. |
| The transition into this state occurs is signaled through event objects |
| or callback functions associated with a command.</p> |
| </dd> |
| <dt class="hdlist1">Compute Device Memory </dt> |
| <dd> |
| <p>This refers to one or more memories attached to the compute device.</p> |
| </dd> |
| <dt class="hdlist1">Compute Unit </dt> |
| <dd> |
| <p>An OpenCL <em>device</em> has one or more <em>compute units</em>. |
| A <em>work-group</em> executes on a single <em>compute unit</em>. |
| A <em>compute unit</em> is composed of one or more <em>processing elements</em> and |
| <em>local memory</em>. |
| A <em>compute unit</em> may also include dedicated texture filter units that |
| can be accessed by its processing elements.</p> |
| </dd> |
| <dt class="hdlist1">Concurrency </dt> |
| <dd> |
| <p>A property of a system in which a set of tasks in a system can remain |
| active and make progress at the same time. |
| To utilize concurrent execution when running a program, a programmer |
| must identify the concurrency in their problem, expose it within the |
| source code, and then exploit it using a notation that supports |
| concurrency.</p> |
| </dd> |
| <dt class="hdlist1">Constant Memory </dt> |
| <dd> |
| <p>A region of <em>global memory</em> that remains constant during the execution |
| of a <em>kernel</em>. |
| The <em>host</em> allocates and initializes memory objects placed into |
| <em>constant memory</em>.</p> |
| </dd> |
| <dt class="hdlist1">Context </dt> |
| <dd> |
| <p>The environment within which the kernels execute and the domain in which |
| synchronization and memory management is defined. |
| The <em>context</em> includes a set of <em>devices</em>, the memory accessible to |
| those <em>devices</em>, the corresponding memory properties and one or more |
| <em>command-queues</em> used to schedule execution of a <em>kernel(s)</em> or |
| operations on <em>memory objects</em>.</p> |
| </dd> |
| <dt class="hdlist1">Control flow </dt> |
| <dd> |
| <p>The flow of instructions executed by a work-item. |
| Multiple logically related work items may or may not execute the same |
| control flow. |
| The control flow is said to be <em>converged</em> if all the work-items in the |
| set execution the same stream of instructions. |
| In a <em>diverged</em> control flow, the work-items in the set execute |
| different instructions. |
| At a later point, if a diverged control flow becomes converged, it is |
| said to be a re-converged control flow.</p> |
| </dd> |
| <dt class="hdlist1">Converged control flow </dt> |
| <dd> |
| <p>See <em>Control flow</em>.</p> |
| </dd> |
| <dt class="hdlist1">Custom Device </dt> |
| <dd> |
| <p>An OpenCL <em>device</em> that fully implements the OpenCL Runtime but does not |
| support <em>programs</em> written in OpenCL C. |
| A custom device may be specialized non-programmable hardware that is |
| very power efficient and performant for directed tasks or hardware with |
| limited programmable capabilities such as specialized DSPs. |
| Custom devices are not OpenCL conformant. |
| Custom devices may support an online compiler. |
| Programs for custom devices can be created using the OpenCL runtime APIs |
| that allow OpenCL programs to be created from source (if an online |
| compiler is supported) and/or binary, or from <em>built-in kernels</em> |
| supported by the <em>device</em>. |
| See also <em>Device</em>.</p> |
| </dd> |
| <dt class="hdlist1">Data Parallel Programming Model </dt> |
| <dd> |
| <p>Traditionally, this term refers to a programming model where concurrency |
| is expressed as instructions from a single program applied to multiple |
| elements within a set of data structures. |
| The term has been generalized in OpenCL to refer to a model wherein a |
| set of instructions from a single program are applied concurrently to |
| each point within an abstract domain of indices.</p> |
| </dd> |
| <dt class="hdlist1">Data race </dt> |
| <dd> |
| <p>The execution of a program contains a data race if it contains two |
| actions in different work items or host threads where (1) one action |
| modifies a memory location and the other action reads or modifies the |
| same memory location, and (2) at least one of these actions is not |
| atomic, or the corresponding memory scopes are not inclusive, and (3) |
| the actions are global actions unordered by the global-happens-before |
| relation or are local actions unordered by the local-happens before |
| relation.</p> |
| </dd> |
| <dt class="hdlist1">Deprecation </dt> |
| <dd> |
| <p>Existing features are marked as deprecated if their usage is not |
| recommended as that feature is being de-emphasized, superseded and may |
| be removed from a future version of the specification.</p> |
| </dd> |
| <dt class="hdlist1">Device </dt> |
| <dd> |
| <p>A <em>device</em> is a collection of <em>compute units</em>. |
| A <em>command-queue</em> is used to queue <em>commands</em> to a <em>device</em>. |
| Examples of <em>commands</em> include executing <em>kernels</em>, or reading and |
| writing <em>memory objects</em>. |
| OpenCL devices typically correspond to a GPU, a multi-core CPU, and |
| other processors such as DSPs and the Cell/B.E. |
| processor.</p> |
| </dd> |
| <dt class="hdlist1">Device-side enqueue </dt> |
| <dd> |
| <p>A mechanism whereby a kernel-instance is enqueued by a kernel-instance |
| running on a device without direct involvement by the host program. |
| This produces <em>nested parallelism</em>; i.e. additional levels of |
| concurrency are nested inside a running kernel-instance. |
| The kernel-instance executing on a device (the <em>parent kernel</em>) enqueues |
| a kernel-instance (the <em>child kernel</em>) to a device-side command queue. |
| Child and parent kernels execute asynchronously though a parent kernel |
| does not complete until all of its child-kernels have completed.</p> |
| </dd> |
| <dt class="hdlist1">Diverged control flow </dt> |
| <dd> |
| <p>See <em>Control flow</em>.</p> |
| </dd> |
| <dt class="hdlist1">Ended </dt> |
| <dd> |
| <p>The fifth state in the six state model for the execution of a command. |
| The transition into this state occurs when execution of a command has |
| ended. |
| When a Kernel-enqueue command ends, all of the work-groups associated |
| with that command have finished their execution.</p> |
| </dd> |
| <dt class="hdlist1">Event Object </dt> |
| <dd> |
| <p>An <em>event object</em> encapsulates the status of an operation such as a |
| <em>command</em>. |
| It can be used to synchronize operations in a context.</p> |
| </dd> |
| <dt class="hdlist1">Event Wait List </dt> |
| <dd> |
| <p>An <em>event wait list</em> is a list of <em>event objects</em> that can be used to |
| control when a particular <em>command</em> begins execution.</p> |
| </dd> |
| <dt class="hdlist1">Fence </dt> |
| <dd> |
| <p>A memory ordering operation without an associated atomic object. |
| A fence can use the <em>acquire semantics, release semantics</em>, or <em>acquire |
| release semantics</em>.</p> |
| </dd> |
| <dt class="hdlist1">Framework </dt> |
| <dd> |
| <p>A software system that contains the set of components to support |
| software development and execution. |
| A <em>framework</em> typically includes libraries, APIs, runtime systems, |
| compilers, etc.</p> |
| </dd> |
| <dt class="hdlist1">Generic address space </dt> |
| <dd> |
| <p>An address space that include the <em>private</em>, <em>local</em>, and <em>global</em> |
| address spaces available to a device. |
| The generic address space supports conversion of pointers to and from |
| private, local and global address spaces, and hence lets a programmer |
| write a single function that at compile time can take arguments from any |
| of the three named address spaces.</p> |
| </dd> |
| <dt class="hdlist1">Global Happens before </dt> |
| <dd> |
| <p>See <em>Happens before</em>.</p> |
| </dd> |
| <dt class="hdlist1">Global ID </dt> |
| <dd> |
| <p>A <em>global ID</em> is used to uniquely identify a <em>work-item</em> and is derived |
| from the number of <em>global work-items</em> specified when executing a |
| <em>kernel</em>. |
| The <em>global ID</em> is a N-dimensional value that starts at (0, 0, …​ 0). |
| See also <em>Local ID</em>.</p> |
| </dd> |
| <dt class="hdlist1">Global Memory </dt> |
| <dd> |
| <p>A memory region accessible to all <em>work-items</em> executing in a <em>context</em>. |
| It is accessible to the <em>host</em> using <em>commands</em> such as read, write and |
| map. |
| <em>Global memory</em> is included within the <em>generic address space</em> that |
| includes the private and local address spaces.</p> |
| </dd> |
| <dt class="hdlist1">GL share group </dt> |
| <dd> |
| <p>A <em>GL share group</em> object manages shared OpenGL or OpenGL ES resources |
| such as textures, buffers, framebuffers, and renderbuffers and is |
| associated with one or more GL context objects. |
| The <em>GL share group</em> is typically an opaque object and not directly |
| accessible.</p> |
| </dd> |
| <dt class="hdlist1">Handle </dt> |
| <dd> |
| <p>An opaque type that references an <em>object</em> allocated by OpenCL. |
| Any operation on an <em>object</em> occurs by reference to that objects handle.</p> |
| </dd> |
| <dt class="hdlist1">Happens before </dt> |
| <dd> |
| <p>An ordering relationship between operations that execute on multiple |
| units of execution. |
| If an operation A happens-before operation B then A must occur before B; |
| in particular, any value written by A will be visible to B. |
| We define two separate happens before relations: <em>global-happens-before</em> |
| and <em>local-happens-before</em>. |
| These are defined in <a href="#memory-ordering-rules">Memory Model: Memory |
| Ordering Rules</a>.</p> |
| </dd> |
| <dt class="hdlist1">Host </dt> |
| <dd> |
| <p>The <em>host</em> interacts with the <em>context</em> using the OpenCL API.</p> |
| </dd> |
| <dt class="hdlist1">Host-thread </dt> |
| <dd> |
| <p>The unit of execution that executes the statements in the host program.</p> |
| </dd> |
| <dt class="hdlist1">Host pointer </dt> |
| <dd> |
| <p>A pointer to memory that is in the virtual address space on the <em>host</em>.</p> |
| </dd> |
| <dt class="hdlist1">Illegal </dt> |
| <dd> |
| <p>Behavior of a system that is explicitly not allowed and will be reported |
| as an error when encountered by OpenCL.</p> |
| </dd> |
| <dt class="hdlist1">Image Object </dt> |
| <dd> |
| <p>A <em>memory object</em> that stores a two- or three-dimensional structured |
| array. |
| Image data can only be accessed with read and write functions. |
| The read functions use a <em>sampler</em>.</p> |
| <div class="openblock"> |
| <div class="content"> |
| <div class="paragraph"> |
| <p>The <em>image object</em> encapsulates the following information:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Dimensions of the image.</p> |
| </li> |
| <li> |
| <p>Description of each element in the image.</p> |
| </li> |
| <li> |
| <p>Properties that describe usage information and which region to allocate |
| from.</p> |
| </li> |
| <li> |
| <p>Image data.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The elements of an image are selected from a list of predefined image |
| formats.</p> |
| </div> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">Implementation Defined </dt> |
| <dd> |
| <p>Behavior that is explicitly allowed to vary between conforming |
| implementations of OpenCL. |
| An OpenCL implementor is required to document the implementation-defined |
| behavior.</p> |
| </dd> |
| <dt class="hdlist1">Independent Forward Progress </dt> |
| <dd> |
| <p>If an entity supports independent forward progress, then if it is |
| otherwise not dependent on any actions due to be performed by any other |
| entity (for example it does not wait on a lock held by, and thus that |
| must be released by, any other entity), then its execution cannot be |
| blocked by the execution of any other entity in the system (it will not |
| be starved). |
| Work items in a subgroup, for example, typically do not support |
| independent forward progress, so one work item in a subgroup may be |
| completely blocked (starved) if a different work item in the same |
| subgroup enters a spin loop.</p> |
| </dd> |
| <dt class="hdlist1">In-order Execution </dt> |
| <dd> |
| <p>A model of execution in OpenCL where the <em>commands</em> in a <em>command-queue</em> |
| are executed in order of submission with each <em>command</em> running to |
| completion before the next one begins. |
| See Out-of-order Execution.</p> |
| </dd> |
| <dt class="hdlist1">Intermediate Language </dt> |
| <dd> |
| <p>A lower-level language that may be used to create programs. |
| SPIR-V is a required IL for OpenCL 2.2 runtimes. |
| Additional ILs may be accepted on an implementation-defined basis.</p> |
| </dd> |
| <dt class="hdlist1">Kernel </dt> |
| <dd> |
| <p>A <em>kernel</em> is a function declared in a <em>program</em> and executed on an |
| OpenCL <em>device</em>. |
| A <em>kernel</em> is identified by the kernel or kernel qualifier applied to |
| any function defined in a <em>program</em>.</p> |
| </dd> |
| <dt class="hdlist1">Kernel-instance </dt> |
| <dd> |
| <p>The work carried out by an OpenCL program occurs through the execution |
| of kernel-instances on devices. |
| The kernel instance is the <em>kernel object</em>, the values associated with |
| the arguments to the kernel, and the parameters that define the |
| <em>NDRange</em> index space.</p> |
| </dd> |
| <dt class="hdlist1">Kernel Object </dt> |
| <dd> |
| <p>A <em>kernel object</em> encapsulates a specific <code>__kernel</code> function declared |
| in a <em>program</em> and the argument values to be used when executing this |
| <code>__kernel</code> function.</p> |
| </dd> |
| <dt class="hdlist1">Kernel Language </dt> |
| <dd> |
| <p>A language that is used to create source code for kernel. |
| Supported kernel languages include OpenCL C, OpenCL C++, and OpenCL |
| dialect of SPIR-V.</p> |
| </dd> |
| <dt class="hdlist1">Launch </dt> |
| <dd> |
| <p>The transition of a command from the <em>submitted</em> state to the <em>ready</em> |
| state. |
| See <em>Ready</em>.</p> |
| </dd> |
| <dt class="hdlist1">Local ID </dt> |
| <dd> |
| <p>A <em>local ID</em> specifies a unique <em>work-item ID</em> within a given |
| <em>work-group</em> that is executing a <em>kernel</em>. |
| The <em>local ID</em> is a N-dimensional value that starts at (0, 0, …​ 0). |
| See also <em>Global ID</em>.</p> |
| </dd> |
| <dt class="hdlist1">Local Memory </dt> |
| <dd> |
| <p>A memory region associated with a <em>work-group</em> and accessible only by |
| <em>work-items</em> in that <em>work-group</em>. |
| <em>Local memory</em> is included within the <em>generic address space</em> that |
| includes the private and global address spaces.</p> |
| </dd> |
| <dt class="hdlist1">Marker </dt> |
| <dd> |
| <p>A <em>command</em> queued in a <em>command-queue</em> that can be used to tag all |
| <em>commands</em> queued before the <em>marker</em> in the <em>command-queue</em>. |
| The <em>marker</em> command returns an <em>event</em> which can be used by the |
| <em>application</em> to queue a wait on the marker event i.e. wait for all |
| commands queued before the <em>marker</em> command to complete.</p> |
| </dd> |
| <dt class="hdlist1">Memory Consistency Model </dt> |
| <dd> |
| <p>Rules that define which values are observed when multiple units of |
| execution load data from any shared memory plus the synchronization |
| operations that constrain the order of memory operations and define |
| synchronization relationships. |
| The memory consistency model in OpenCL is based on the memory model from |
| the ISO C11 programming language.</p> |
| </dd> |
| <dt class="hdlist1">Memory Objects </dt> |
| <dd> |
| <p>A <em>memory object</em> is a handle to a reference counted region of <em>Global |
| Memory</em>. |
| Also see <em>Buffer Object</em> and <em>Image Object</em>.</p> |
| </dd> |
| <dt class="hdlist1">Memory Regions (or Pools) </dt> |
| <dd> |
| <p>A distinct address space in OpenCL. |
| <em>Memory regions</em> may overlap in physical memory though OpenCL will treat |
| them as logically distinct. |
| The <em>memory regions</em> are denoted as <em>private</em>, <em>local</em>, <em>constant,</em> and |
| <em>global</em>.</p> |
| </dd> |
| <dt class="hdlist1">Memory Scopes </dt> |
| <dd> |
| <p>These memory scopes define a hierarchy of visibilities when analyzing |
| the ordering constraints of memory operations. |
| They are defined by the values of the <strong>memory_scope</strong> enumeration |
| constant. |
| Current values are <strong>memory_scope_work_item</strong> (memory constraints only |
| apply to a single work-item and in practice apply only to image |
| operations), <strong>memory_scope_sub_group</strong> (memory-ordering constraints only |
| apply to work-items executing in a sub-group), <strong>memory_scope_work_group</strong> |
| (memory-ordering constraints only apply to work-items executing in a |
| work-group), <strong>memory_scope_device</strong> (memory-ordering constraints only |
| apply to work-items executing on a single device) and |
| <strong>memory_scope_all_svm_devices</strong> (memory-ordering constraints only apply |
| to work-items executing across multiple devices and when using shared |
| virtual memory).</p> |
| </dd> |
| <dt class="hdlist1">Modification Order </dt> |
| <dd> |
| <p>All modifications to a particular atomic object M occur in some |
| particular <em>total order</em>, called the <em>modification order</em> of M. |
| If A and B are modifications of an atomic object M, and A happens-before |
| B, then A shall precede B in the modification order of M. |
| Note that the modification order of an atomic object M is independent of |
| whether M is in local or global memory.</p> |
| </dd> |
| <dt class="hdlist1">Nested Parallelism </dt> |
| <dd> |
| <p>See <em>device-side enqueue</em>.</p> |
| </dd> |
| <dt class="hdlist1">Object </dt> |
| <dd> |
| <p>Objects are abstract representation of the resources that can be |
| manipulated by the OpenCL API. |
| Examples include <em>program objects</em>, <em>kernel objects</em>, and <em>memory |
| objects</em>.</p> |
| </dd> |
| <dt class="hdlist1">Out-of-Order Execution </dt> |
| <dd> |
| <p>A model of execution in which <em>commands</em> placed in the <em>work queue</em> may |
| begin and complete execution in any order consistent with constraints |
| imposed by <em>event wait lists_and_command-queue barrier</em>. |
| See <em>In-order Execution</em>.</p> |
| </dd> |
| <dt class="hdlist1">Parent device </dt> |
| <dd> |
| <p>The OpenCL <em>device</em> which is partitioned to create <em>sub-devices</em>. |
| Not all <em>parent devices</em> are <em>root devices</em>. |
| A <em>root device</em> might be partitioned and the <em>sub-devices</em> partitioned |
| again. |
| In this case, the first set of <em>sub-devices</em> would be <em>parent devices</em> |
| of the second set, but not the <em>root devices</em>. |
| Also see <em>Device</em>, <em>parent device</em> and <em>root device</em>.</p> |
| </dd> |
| <dt class="hdlist1">Parent kernel </dt> |
| <dd> |
| <p>see <em>Device-side enqueue</em>.</p> |
| </dd> |
| <dt class="hdlist1">Pipe </dt> |
| <dd> |
| <p>The <em>pipe</em> memory object conceptually is an ordered sequence of data |
| items. |
| A pipe has two endpoints: a write endpoint into which data items are |
| inserted, and a read endpoint from which data items are removed. |
| At any one time, only one kernel instance may write into a pipe, and |
| only one kernel instance may read from a pipe. |
| To support the producer consumer design pattern, one kernel instance |
| connects to the write endpoint (the producer) while another kernel |
| instance connects to the reading endpoint (the consumer).</p> |
| </dd> |
| <dt class="hdlist1">Platform </dt> |
| <dd> |
| <p>The <em>host</em> plus a collection of <em>devices</em> managed by the OpenCL |
| <em>framework</em> that allow an application to share <em>resources</em> and execute |
| <em>kernels</em> on <em>devices</em> in the <em>platform</em>.</p> |
| </dd> |
| <dt class="hdlist1">Private Memory </dt> |
| <dd> |
| <p>A region of memory private to a <em>work-item</em>. |
| Variables defined in one <em>work-items</em> <em>private memory</em> are not visible |
| to another <em>work-item</em>.</p> |
| </dd> |
| <dt class="hdlist1">Processing Element </dt> |
| <dd> |
| <p>A virtual scalar processor. |
| A work-item may execute on one or more processing elements.</p> |
| </dd> |
| <dt class="hdlist1">Program </dt> |
| <dd> |
| <p>An OpenCL <em>program</em> consists of a set of <em>kernels</em>. |
| <em>Programs</em> may also contain auxiliary functions called by the |
| <code>__kernel</code> functions and constant data.</p> |
| </dd> |
| <dt class="hdlist1">Program Object </dt> |
| <dd> |
| <p>A <em>program object</em> encapsulates the following information:</p> |
| <div class="openblock"> |
| <div class="content"> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>A reference to an associated <em>context</em>.</p> |
| </li> |
| <li> |
| <p>A <em>program</em> source or binary.</p> |
| </li> |
| <li> |
| <p>The latest successfully built program executable, the list of <em>devices</em> |
| for which the program executable is built, the build options used and a |
| build log.</p> |
| </li> |
| <li> |
| <p>The number of <em>kernel objects</em> currently attached.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">Queued </dt> |
| <dd> |
| <p>The first state in the six state model for the execution of a command. |
| The transition into this state occurs when the command is enqueued into |
| a command-queue.</p> |
| </dd> |
| <dt class="hdlist1">Ready </dt> |
| <dd> |
| <p>The third state in the six state model for the execution of a command. |
| The transition into this state occurs when pre-requisites constraining |
| execution of a command have been met; i.e. the command has been |
| launched. |
| When a kernel-enqueue command is launched, work-groups associated with |
| the command are placed in a devices work-pool from which they are |
| scheduled for execution.</p> |
| </dd> |
| <dt class="hdlist1">Re-converged Control Flow </dt> |
| <dd> |
| <p>see <em>Control flow</em>.</p> |
| </dd> |
| <dt class="hdlist1">Reference Count </dt> |
| <dd> |
| <p>The life span of an OpenCL object is determined by its <em>reference |
| count</em>, an internal count of the number of references to the object. |
| When you create an object in OpenCL, its <em>reference count</em> is set to |
| one. |
| Subsequent calls to the appropriate <em>retain</em> API (such as |
| <strong>clRetainContext</strong>, <strong>clRetainCommandQueue</strong>) increment the <em>reference |
| count</em>. |
| Calls to the appropriate <em>release</em> API (such as <strong>clReleaseContext</strong>, |
| <strong>clReleaseCommandQueue</strong>) decrement the <em>reference count</em>. |
| Implementations may also modify the <em>reference count</em>, e.g. to track |
| attached objects or to ensure correct operation of in-progress or |
| scheduled activities. |
| The object becomes inaccessible to host code when the number of |
| <em>release</em> operations performed matches the number of <em>retain</em> operations |
| plus the allocation of the object. |
| At this point the reference count may be zero but this is not |
| guaranteed.</p> |
| </dd> |
| <dt class="hdlist1">Relaxed Consistency </dt> |
| <dd> |
| <p>A memory consistency model in which the contents of memory visible to |
| different <em>work-items</em> or <em>commands</em> may be different except at a |
| <em>barrier</em> or other explicit synchronization points.</p> |
| </dd> |
| <dt class="hdlist1">Relaxed Semantics </dt> |
| <dd> |
| <p>A memory order semantics for atomic operations that implies no order |
| constraints. |
| The operation is <em>atomic</em> but it has no impact on the order of memory |
| operations.</p> |
| </dd> |
| <dt class="hdlist1">Release Semantics </dt> |
| <dd> |
| <p>One of the memory order semantics defined for synchronization |
| operations. |
| Release semantics apply to atomic operations that store to memory. |
| Given two units of execution, <strong>A</strong> and <strong>B</strong>, acting on a shared atomic |
| object <strong>M</strong>, if <strong>A</strong> uses an atomic store of <strong>M</strong> with release semantics to |
| synchronize-with an atomic load to <strong>M</strong> by <strong>B</strong> that used acquire |
| semantics, then <strong>A</strong>'s atomic store will occur <em>after</em> any prior |
| operations by <strong>A</strong>. |
| Note that the memory orders <em>acquire</em>, <em>sequentially consistent</em>, and |
| <em>acquire_release</em> all include <em>acquire semantics</em> and effectively pair |
| with a store using release semantics.</p> |
| </dd> |
| <dt class="hdlist1">Remainder work-groups </dt> |
| <dd> |
| <p>When the work-groups associated with a kernel-instance are defined, the |
| sizes of a work-group in each dimension may not evenly divide the size |
| of the NDRange in the corresponding dimensions. |
| The result is a collection of work-groups on the boundaries of the |
| NDRange that are smaller than the base work-group size. |
| These are known as <em>remainder work-groups</em>.</p> |
| </dd> |
| <dt class="hdlist1">Running </dt> |
| <dd> |
| <p>The fourth state in the six state model for the execution of a command. |
| The transition into this state occurs when the execution of the command |
| starts. |
| When a Kernel-enqueue command starts, one or more work-groups associated |
| with the command start to execute.</p> |
| </dd> |
| <dt class="hdlist1">Root device </dt> |
| <dd> |
| <p>A <em>root device</em> is an OpenCL <em>device</em> that has not been partitioned. |
| Also see <em>Device</em>, <em>Parent device</em> and <em>Root device</em>.</p> |
| </dd> |
| <dt class="hdlist1">Resource </dt> |
| <dd> |
| <p>A class of <em>objects</em> defined by OpenCL. |
| An instance of a <em>resource</em> is an <em>object</em>. |
| The most common <em>resources</em> are the <em>context</em>, <em>command-queue</em>, <em>program |
| objects</em>, <em>kernel objects</em>, and <em>memory objects</em>. |
| Computational resources are hardware elements that participate in the |
| action of advancing a program counter. |
| Examples include the <em>host</em>, <em>devices</em>, <em>compute units</em> and <em>processing |
| elements</em>.</p> |
| </dd> |
| <dt class="hdlist1">Retain, Release </dt> |
| <dd> |
| <p>The action of incrementing (retain) and decrementing (release) the |
| reference count using an OpenCL <em>object</em>. |
| This is a book keeping functionality to make sure the system doesn’t |
| remove an <em>object</em> before all instances that use this <em>object</em> have |
| finished. |
| Refer to <em>Reference Count</em>.</p> |
| </dd> |
| <dt class="hdlist1">Sampler </dt> |
| <dd> |
| <p>An <em>object</em> that describes how to sample an image when the image is read |
| in the <em>kernel</em>. |
| The image read functions take a <em>sampler</em> as an argument. |
| The <em>sampler</em> specifies the image addressing-mode i.e. how out-of-range |
| image coordinates are handled, the filter mode, and whether the input |
| image coordinate is a normalized or unnormalized value.</p> |
| </dd> |
| <dt class="hdlist1">Scope inclusion </dt> |
| <dd> |
| <p>Two actions <strong>A</strong> and <strong>B</strong> are defined to have an inclusive scope if they |
| have the same scope <strong>P</strong> such that: (1) if <strong>P</strong> is |
| <strong>memory_scope_sub_group</strong>, and <strong>A</strong> and <strong>B</strong> are executed by work-items |
| within the same sub-group, or (2) if <strong>P</strong> is <strong>memory_scope_work_group</strong>, |
| and <strong>A</strong> and <strong>B</strong> are executed by work-items within the same work-group, |
| or (3) if <strong>P</strong> is <strong>memory_scope_device</strong>, and <strong>A</strong> and <strong>B</strong> are executed by |
| work-items on the same device, or (4) if <strong>P</strong> is |
| <strong>memory_scope_all_svm_devices</strong>, if <strong>A</strong> and <strong>B</strong> are executed by host |
| threads or by work-items on one or more devices that can share SVM |
| memory with each other and the host process.</p> |
| </dd> |
| <dt class="hdlist1">Sequenced before </dt> |
| <dd> |
| <p>A relation between evaluations executed by a single unit of execution. |
| Sequenced-before is an asymmetric, transitive, pair-wise relation that |
| induces a partial order between evaluations. |
| Given any two evaluations A and B, if A is sequenced-before B, then the |
| execution of A shall precede the execution of B.</p> |
| </dd> |
| <dt class="hdlist1">Sequential consistency </dt> |
| <dd> |
| <p>Sequential consistency interleaves the steps executed by each unit of |
| execution. |
| Each access to a memory location sees the last assignment to that |
| location in that interleaving.</p> |
| </dd> |
| <dt class="hdlist1">Sequentially consistent semantics </dt> |
| <dd> |
| <p>One of the memory order semantics defined for synchronization |
| operations. |
| When using sequentially-consistent synchronization operations, the loads |
| and stores within one unit of execution appear to execute in program |
| order (i.e., the sequenced-before order), and loads and stores from |
| different units of execution appear to be simply interleaved.</p> |
| </dd> |
| <dt class="hdlist1">Shared Virtual Memory (SVM) </dt> |
| <dd> |
| <p>An address space exposed to both the host and the devices within a |
| context. |
| SVM causes addresses to be meaningful between the host and all of the |
| devices within a context and therefore supports the use of pointer based |
| data structures in OpenCL kernels. |
| It logically extends a portion of the global memory into the host |
| address space therefore giving work-items access to the host address |
| space. |
| There are three types of SVM in OpenCL:</p> |
| <div class="openblock"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>Coarse-Grained buffer SVM</em> </dt> |
| <dd> |
| <p>Sharing occurs at the granularity of regions of OpenCL buffer memory |
| objects.</p> |
| </dd> |
| <dt class="hdlist1"><em>Fine-Grained buffer SVM</em> </dt> |
| <dd> |
| <p>Sharing occurs at the granularity of individual loads/stores into bytes |
| within OpenCL buffer memory objects.</p> |
| </dd> |
| <dt class="hdlist1"><em>Fine-Grained system SVM</em> </dt> |
| <dd> |
| <p>Sharing occurs at the granularity of individual loads/stores into bytes |
| occurring anywhere within the host memory.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">SIMD </dt> |
| <dd> |
| <p>Single Instruction Multiple Data. |
| A programming model where a <em>kernel</em> is executed concurrently on |
| multiple <em>processing elements</em> each with its own data and a shared |
| program counter. |
| All <em>processing elements</em> execute a strictly identical set of |
| instructions.</p> |
| </dd> |
| <dt class="hdlist1">Specialization constants </dt> |
| <dd> |
| <p>Specialization is intended for constant objects that will not have known |
| constant values until after initial generation of a module in an intermediate |
| representation format (e.g. SPIR-V). Such objects are called specialization |
| constants. |
| Application might provide values for the specialization constants that |
| will be used when program is built from the intermediate format. |
| Specialization constants that do not receive a value from an application |
| shall use default values as defined in OpenCL C++ or SPIR-V specification.</p> |
| </dd> |
| <dt class="hdlist1">SPMD </dt> |
| <dd> |
| <p>Single Program Multiple Data. |
| A programming model where a <em>kernel</em> is executed concurrently on |
| multiple <em>processing elements</em> each with its own data and its own |
| program counter. |
| Hence, while all computational resources run the same <em>kernel</em> they |
| maintain their own instruction counter and due to branches in a |
| <em>kernel</em>, the actual sequence of instructions can be quite different |
| across the set of <em>processing elements</em>.</p> |
| </dd> |
| <dt class="hdlist1">Sub-device </dt> |
| <dd> |
| <p>An OpenCL <em>device</em> can be partitioned into multiple <em>sub-devices</em>. |
| The new <em>sub-devices</em> alias specific collections of compute units within |
| the parent <em>device</em>, according to a partition scheme. |
| The <em>sub-devices</em> may be used in any situation that their parent |
| <em>device</em> may be used. |
| Partitioning a <em>device</em> does not destroy the parent <em>device</em>, which may |
| continue to be used along side and intermingled with its child |
| <em>sub-devices</em>. |
| Also see <em>Device</em>, <em>Parent device</em> and <em>Root device</em>.</p> |
| </dd> |
| <dt class="hdlist1">Sub-group </dt> |
| <dd> |
| <p>Sub-groups are an implementation-dependent grouping of work-items within |
| a work-group. |
| The size and number of sub-groups is implementation-defined.</p> |
| </dd> |
| <dt class="hdlist1">Sub-group Barrier </dt> |
| <dd> |
| <p>See <em>Barrier</em>.</p> |
| </dd> |
| <dt class="hdlist1">Submitted </dt> |
| <dd> |
| <p>The second state in the six state model for the execution of a command. |
| The transition into this state occurs when the command is flushed from |
| the command-queue and submitted for execution on the device. |
| Once submitted, a programmer can assume a command will execute once its |
| prerequisites have been met.</p> |
| </dd> |
| <dt class="hdlist1">SVM Buffer </dt> |
| <dd> |
| <p>A memory allocation enabled to work with <em>Shared Virtual Memory (SVM)</em>. |
| Depending on how the SVM buffer is created, it can be a coarse-grained |
| or fine-grained SVM buffer. |
| Optionally it may be wrapped by a <em>Buffer Object</em>. |
| See <em>Shared Virtual Memory (SVM)</em>.</p> |
| </dd> |
| <dt class="hdlist1">Synchronization </dt> |
| <dd> |
| <p>Synchronization refers to mechanisms that constrain the order of |
| execution and the visibility of memory operations between two or more |
| units of execution.</p> |
| </dd> |
| <dt class="hdlist1">Synchronization operations </dt> |
| <dd> |
| <p>Operations that define memory order constraints in a program. |
| They play a special role in controlling how memory operations in one |
| unit of execution (such as work-items or, when using SVM a host thread) |
| are made visible to another. |
| Synchronization operations in OpenCL include <em>atomic operations</em> and |
| <em>fences</em>.</p> |
| </dd> |
| <dt class="hdlist1">Synchronization point </dt> |
| <dd> |
| <p>A synchronization point between a pair of commands (A and B) assures |
| that results of command A happens-before command B is launched (i.e. |
| enters the ready state) .</p> |
| </dd> |
| <dt class="hdlist1">Synchronizes with </dt> |
| <dd> |
| <p>A relation between operations in two different units of execution that |
| defines a memory order constraint in global memory |
| (<em>global-synchronizes-with</em>) or local memory |
| (<em>local-synchronizes-with</em>).</p> |
| </dd> |
| <dt class="hdlist1">Task Parallel Programming Model </dt> |
| <dd> |
| <p>A programming model in which computations are expressed in terms of |
| multiple concurrent tasks executing in one or more <em>command-queues</em>. |
| The concurrent tasks can be running different <em>kernels</em>.</p> |
| </dd> |
| <dt class="hdlist1">Thread-safe </dt> |
| <dd> |
| <p>An OpenCL API call is considered to be <em>thread-safe</em> if the internal |
| state as managed by OpenCL remains consistent when called simultaneously |
| by multiple <em>host</em> threads. |
| OpenCL API calls that are <em>thread-safe</em> allow an application to call |
| these functions in multiple <em>host</em> threads without having to implement |
| mutual exclusion across these <em>host</em> threads i.e. they are also |
| re-entrant-safe.</p> |
| </dd> |
| <dt class="hdlist1">Undefined </dt> |
| <dd> |
| <p>The behavior of an OpenCL API call, built-in function used inside a |
| <em>kernel</em> or execution of a <em>kernel</em> that is explicitly not defined by |
| OpenCL. |
| A conforming implementation is not required to specify what occurs when |
| an undefined construct is encountered in OpenCL.</p> |
| </dd> |
| <dt class="hdlist1">Unit of execution </dt> |
| <dd> |
| <p>A generic term for a process, OS managed thread running on the host (a |
| host-thread), kernel-instance, host program, work-item or any other |
| executable agent that advances the work associated with a program.</p> |
| </dd> |
| <dt class="hdlist1">Work-group </dt> |
| <dd> |
| <p>A collection of related <em>work-items</em> that execute on a single <em>compute |
| unit</em>. |
| The <em>work-items</em> in the group execute the same <em>kernel-instance</em> and |
| share <em>local</em> <em>memory</em> and <em>work-group functions</em>.</p> |
| </dd> |
| <dt class="hdlist1">Work-group Barrier </dt> |
| <dd> |
| <p>See <em>Barrier</em>.</p> |
| </dd> |
| <dt class="hdlist1">Work-group Function </dt> |
| <dd> |
| <p>A function that carries out collective operations across all the |
| work-items in a work-group. |
| Available collective operations are a barrier, reduction, broadcast, |
| prefix sum, and evaluation of a predicate. |
| A work-group function must occur within a <em>converged control flow</em>; i.e. |
| all work-items in the work-group must encounter precisely the same |
| work-group function.</p> |
| </dd> |
| <dt class="hdlist1">Work-group Synchronization </dt> |
| <dd> |
| <p>Constraints on the order of execution for work-items in a single |
| work-group.</p> |
| </dd> |
| <dt class="hdlist1">Work-pool </dt> |
| <dd> |
| <p>A logical pool associated with a device that holds commands and |
| work-groups from kernel-instances that are ready to execute. |
| OpenCL does not constrain the order that commands and work-groups are |
| scheduled for execution from the work-pool; i.e. a programmer must |
| assume that they could be interleaved. |
| There is one work-pool per device used by all command-queues associated |
| with that device. |
| The work-pool may be implemented in any manner as long as it assures |
| that work-groups placed in the pool will eventually execute.</p> |
| </dd> |
| <dt class="hdlist1">Work-item </dt> |
| <dd> |
| <p>One of a collection of parallel executions of a <em>kernel</em> invoked on a |
| <em>device</em> by a <em>command</em>. |
| A <em>work-item</em> is executed by one or more <em>processing elements</em> as part |
| of a <em>work-group</em> executing on a <em>compute unit</em>. |
| A <em>work-item</em> is distinguished from other work-items by its <em>global ID</em> |
| or the combination of its <em>work-group</em> ID and its <em>local ID</em> within a |
| <em>work-group</em>.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_the_opencl_architecture">3. The OpenCL Architecture</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p><strong>OpenCL</strong> is an open industry standard for programming a heterogeneous |
| collection of CPUs, GPUs and other discrete computing devices organized into |
| a single platform. |
| It is more than a language. |
| OpenCL is a framework for parallel programming and includes a language, API, |
| libraries and a runtime system to support software development. |
| Using OpenCL, for example, a programmer can write general purpose programs |
| that execute on GPUs without the need to map their algorithms onto a 3D |
| graphics API such as OpenGL or DirectX.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The target of OpenCL is expert programmers wanting to write portable yet |
| efficient code. |
| This includes library writers, middleware vendors, and performance oriented |
| application programmers. |
| Therefore OpenCL provides a low-level hardware abstraction plus a framework |
| to support programming and many details of the underlying hardware are |
| exposed.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To describe the core ideas behind OpenCL, we will use a hierarchy of models:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Platform Model</p> |
| </li> |
| <li> |
| <p>Memory Model</p> |
| </li> |
| <li> |
| <p>Execution Model</p> |
| </li> |
| <li> |
| <p>Programming Model</p> |
| </li> |
| </ul> |
| </div> |
| <div class="sect2"> |
| <h3 id="_platform_model">3.1. Platform Model</h3> |
| <div class="paragraph"> |
| <p>The <a href="#platform-model-image">Platform model</a> for OpenCL is defined below. |
| The model consists of a <strong>host</strong> connected to one or more <strong>OpenCL devices</strong>. |
| An OpenCL device is divided into one or more <strong>compute units</strong> (CUs) which are |
| further divided into one or more <strong>processing elements</strong> (PEs). |
| Computations on a device occur within the processing elements.</p> |
| </div> |
| <div class="paragraph"> |
| <p>An OpenCL application is implemented as both host code and device kernel |
| code. |
| The host code portion of an OpenCL application runs on a host processor |
| according to the models native to the host platform. |
| The OpenCL application host code submits the kernel code as commands from |
| the host to OpenCL devices. |
| An OpenCL device executes the commands computation on the processing |
| elements within the device.</p> |
| </div> |
| <div class="paragraph"> |
| <p>An OpenCL device has considerable latitude on how computations are mapped |
| onto the devices processing elements. |
| When processing elements within a compute unit execute the same sequence of |
| statements across the processing elements, the control flow is said to be |
| <em>converged</em>. |
| Hardware optimized for executing a single stream of instructions over |
| multiple processing elements is well suited to converged control flows. |
| When the control flow varies from one processing element to another, it is |
| said to be <em>diverged</em>. |
| While a kernel always begins execution with a converged control flow, due to |
| branching statements within a kernel, converged and diverged control flows |
| may occur within a single kernel. |
| This provides a great deal of flexibility in the algorithms that can be |
| implemented with OpenCL.</p> |
| </div> |
| <div id="platform-model-image" class="imageblock" style="text-align: center"> |
| <div class="content"> |
| <img src="data:image/png;base64,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k6NHjzY37LRhmh+M59Xvg3nHDmBHuLp+rtoAz/j7778n11tvveTIkSOr7TAzZsywcuT+5ptvTrZo0SKpnUDy7LPPTirxJffZZ5+kknNSiTS5xx57JD/88MPkpptummzVqlXykUcesbDbb7998rDDDrNw22yzTVI7EDNbb711cty4cVbOhx56aLJXr17JNm3aJJX8kzfccEPyoYceSq699toW7tRTT7V3ox2EvUswatSo5Lrrrpv866+/7DcYPny4xaEdT1I7KAu71lprJS+99FIL37lz5+SwYcMszZ9++im55557Jq+88kp7HvDkk09amjzniy++aGEmTpxo/oiX+Hr37m1+tZOozkuIVYu65Mk1Q9xbArQcTOpBwsHUFZCqkBgZ+iMtckQe+60jiXkelaxMCuNeG7rZc8Xery454AezJoBnpsx4f0ir3LPHDxIsO1GyzPG5556T//znP3Yq1VtvvSXamcptt91m6h7Ki1EAH54h/eOXkcCjjz5qZcgOl+j7+/TpYyOFs846y8qaE60od96JEr60bdvWJspRFfHuOP3qhRdesLiJgzN6kbj9vfDOCR8E0jrmnnvukaefftrUOOSVOBjl8d3EnXfeaWneddddoh2PjTKoO3zEdcUVV9hzosJ67733bHRCXSJNztnt3r27hecoRkYpPDsmRMNFSPQB0HB8KFsXoLGxRzoN98QTT7RGSOMkT5AKCHZE2EEUhOPeGyykx29/Hg/b0EFZYNBZo07hHgJEd/3HH38YsTHReeSRR5oenDJm8zJIFXLnIyfCoCrbZZddbIsD3gFlzqlUkDZ+rrvuOtOtu9rG6wx+GzdubCqW9u3b2wdT+IGML7vsMksfwub9OLkH35eDPIDp06eb/S233CI33XSThYe4DzjgANGRgHUsXLt27WqqGdLX0Yuly9LbSy65xDoJOj5UQnQE3bp1M3Xg0KFD7dnpdDy9EA0XaxzR03BouBCoS1U0VMiBxsI97hhvfNy7tEzDBIR1gvX4/DdXDHb8duPuQePw33xCD8kgkQIaoadN3pigIz0H9r5sEEOakIvH57pg0gbBfDYk8EysRoLIOVoQQMJ8sYqEjXRPOUGEDv+SlXJF8gdB6Zp3gDtliI4ecgesfiItl8zXXXdds0fXzzsgHHFyT9jTTjvNiP6qq66Sgw8+2OIkL1wB74dVNg46Bjob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" alt="platform model"> |
| </div> |
| <div class="title">Figure 1. Platform Model …​ one host plus one or more compute devices each with one or more compute units composed of one or more processing elements.</div> |
| </div> |
| <div class="paragraph"> |
| <p>Programmers provide programs in the form of SPIR-V source binaries, OpenCL C |
| or OpenCL C++ source strings or implementation-defined binary objects. |
| The OpenCL platform provides a compiler to translate program input of either |
| form into executable program objects. |
| The device code compiler may be <em>online</em> or <em>offline</em>. |
| An <em>online</em> <em>compiler</em> is available during host program execution using |
| standard APIs. |
| An <em>offline compiler</em> is invoked outside of host program control, using |
| platform-specific methods. |
| The OpenCL runtime allows developers to get a previously compiled device |
| program executable and be able to load and execute a previously compiled |
| device program executable.</p> |
| </div> |
| <div class="paragraph"> |
| <p>OpenCL defines two kinds of platform profiles: a <em>full profile</em> and a |
| reduced-functionality <em>embedded profile</em>. |
| A full profile platform must provide an online compiler for all its devices. |
| An embedded platform may provide an online compiler, but is not required to |
| do so.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A device may expose special purpose functionality as a <em>built-in function</em>. |
| The platform provides APIs for enumerating and invoking the built-in |
| functions offered by a device, but otherwise does not define their |
| construction or semantics. |
| A <em>custom device</em> supports only built-in functions, and cannot be programmed |
| via a kernel language.</p> |
| </div> |
| <div class="paragraph"> |
| <p>All device types support the OpenCL execution model, the OpenCL memory |
| model, and the APIs used in OpenCL to manage devices.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The platform model is an abstraction describing how OpenCL views the |
| hardware. |
| The relationship between the elements of the platform model and the hardware |
| in a system may be a fixed property of a device or it may be a dynamic |
| feature of a program dependent on how a compiler optimizes code to best |
| utilize physical hardware.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_execution_model">3.2. Execution Model</h3> |
| <div class="paragraph"> |
| <p>The OpenCL execution model is defined in terms of two distinct units of |
| execution: <strong>kernels</strong> that execute on one or more OpenCL devices and a <strong>host |
| program</strong> that executes on the host. |
| With regard to OpenCL, the kernels are where the "work" associated with a |
| computation occurs. |
| This work occurs through <strong>work-items</strong> that execute in groups |
| (<strong>work-groups</strong>).</p> |
| </div> |
| <div class="paragraph"> |
| <p>A kernel executes within a well-defined context managed by the host. |
| The context defines the environment within which kernels execute. |
| It includes the following resources:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>Devices</strong>: One or more devices exposed by the OpenCL platform.</p> |
| </li> |
| <li> |
| <p><strong>Kernel Objects</strong>:The OpenCL functions with their associated argument |
| values that run on OpenCL devices.</p> |
| </li> |
| <li> |
| <p><strong>Program Objects</strong>:The program source and executable that implement the |
| kernels.</p> |
| </li> |
| <li> |
| <p><strong>Memory Objects</strong>:Variables visible to the host and the OpenCL devices. |
| Instances of kernels operate on these objects as they execute.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The host program uses the OpenCL API to create and manage the context. |
| Functions from the OpenCL API enable the host to interact with a device |
| through a <em>command-queue</em>. |
| Each command-queue is associated with a single device. |
| The commands placed into the command-queue fall into one of three types:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>Kernel-enqueue commands</strong>: Enqueue a kernel for execution on a device.</p> |
| </li> |
| <li> |
| <p><strong>Memory commands</strong>: Transfer data between the host and device memory, |
| between memory objects, or map and unmap memory objects from the host |
| address space.</p> |
| </li> |
| <li> |
| <p><strong>Synchronization commands</strong>: Explicit synchronization points that define |
| order constraints between commands.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>In addition to commands submitted from the host command-queue, a kernel |
| running on a device can enqueue commands to a device-side command queue. |
| This results in <em>child kernels</em> enqueued by a kernel executing on a device |
| (the <em>parent kernel</em>). |
| Regardless of whether the command-queue resides on the host or a device, |
| each command passes through six states.</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p><strong>Queued</strong>: The command is enqueued to a command-queue. |
| A command may reside in the queue until it is flushed either explicitly |
| (a call to <strong>clFlush</strong>) or implicitly by some other command.</p> |
| </li> |
| <li> |
| <p><strong>Submitted</strong>: The command is flushed from the command-queue and submitted |
| for execution on the device. |
| Once flushed from the command-queue, a command will execute after any |
| prerequisites for execution are met.</p> |
| </li> |
| <li> |
| <p><strong>Ready</strong>: All prerequisites constraining execution of a command have been |
| met. |
| The command, or for a kernel-enqueue command the collection of work |
| groups associated with a command, is placed in a device work-pool from |
| which it is scheduled for execution.</p> |
| </li> |
| <li> |
| <p><strong>Running</strong>: Execution of the command starts. |
| For the case of a kernel-enqueue command, one or more work-groups |
| associated with the command start to execute.</p> |
| </li> |
| <li> |
| <p><strong>Ended</strong>: Execution of a command ends. |
| When a Kernel-enqueue command ends, all of the work-groups associated |
| with that command have finished their execution. |
| <em>Immediate side effects</em>, i.e. those associated with the kernel but not |
| necessarily with its child kernels, are visible to other units of |
| execution. |
| These side effects include updates to values in global memory.</p> |
| </li> |
| <li> |
| <p><strong>Complete</strong>: The command and its child commands have finished execution |
| and the status of the event object, if any, associated with the command |
| is set to CL_COMPLETE.</p> |
| </li> |
| </ol> |
| </div> |
| <div class="paragraph"> |
| <p>The <a href="#profiled-states-image">execution states and the transitions between |
| them</a> are summarized below. |
| These states and the concept of a device work-pool are conceptual elements |
| of the execution model. |
| An implementation of OpenCL has considerable freedom in how these are |
| exposed to a program. |
| Five of the transitions, however, are directly observable through a |
| profiling interface. |
| These <a href="#profiled-states-image">profiled states</a> are shown below.</p> |
| </div> |
| <div id="profiled-states-image" class="imageblock" style="text-align: center"> |
| <div class="content"> |
| <img src="data:image/jpg;base64,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wqevIf7De4t/h/f3mtazc3d9cxyyu96+Axtnc7V6LyMcdiR3r16gDzTx34g074a/DRk8OCGJ7iRoLIRvvCuxLO4OT0+Y/XFc58Cfh+ltYL4x1WPzL67ybMScmND1k/3m559PrXmPjiG7tPCHg3Tr2Ga2CtfO0cqFSC1yecH2A/OvrPT7eG0021trcAQQwokYHQKAAP0oAs0UUUAFFFFABRRRQAx445BiRFcejDNVJdE0mf8A12mWUmf79up/mKvUU02gMl/C3h6TG/QdLbHTNnGf6Uz/AIRHw1/0L2lf+Acf+FbNFPml3FZGWvhrQVIK6Jpox0xapx+lW4tPsoP9TZ28f+5Eo/kKs0UrthZAAAMAYooopDCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigArMu9D0+81/TtYnVjfWCSpbkPgASABsjvwK064XxAsp+L3g1lWQxC2vt5AO0fIuM0Ad1RRRQAUUUUAFYN34J8MX2qHUrrQrGW8LBmlaEZYjuexP1reooAzrvQdKvr+K+utPt5rqKJoUkdASEYYZfcHJ4PrVOx8F+GtNAFlolnBgOoKRgHDjawz6EcYrdooAzbrw/pF7pttp9zp8EtpalDBEy8RlBhdvpgVpUUUAeDfF7yfHvwz0/xhpltMq2NxIjrIBuEe4oxOD03Kv4GvQvhP4pj8U+AbCYybru0QWtyCeQ6gAH8Rg/iau+E/B66J4GHhrUnivI388S7VIV1kdmxz7NivC9Pur/4GfFCa0uvNl0G86sB/rISflcf7adCPr6igD6eoqG1uoL60hu7WVJreZA8ciHIZSMgipqACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigArLu9fsbLxBpuiTGT7ZqCSvBhcriMAtk9utalcxq3h67vvH/h3XYniFrp0NykysTuJkUBcDHtQB09FFFABRRRQAUUUUAFFFFABRRRQByfw21y/8R+CLXU9TlWW6kmnVmVAoIWVlHA9gKPiF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" alt="profiled states"> |
| </div> |
| <div class="title">Figure 2. The states and transitions between states defined in the OpenCL execution model. A subset of these transitions is exposed through the <a href="#profiling-operations">profiling interface</a>.</div> |
| </div> |
| <div class="paragraph"> |
| <p>Commands communicate their status through <em>Event objects</em>. |
| Successful completion is indicated by setting the event status associated |
| with a command to CL_COMPLETE. |
| Unsuccessful completion results in abnormal termination of the command which |
| is indicated by setting the event status to a negative value. |
| In this case, the command-queue associated with the abnormally terminated |
| command and all other command-queues in the same context may no longer be |
| available and their behavior is implementation defined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A command submitted to a device will not launch until prerequisites that |
| constrain the order of commands have been resolved. |
| These prerequisites have three sources:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>They may arise from commands submitted to a command-queue that constrain |
| the order in which commands are launched. |
| For example, commands that follow a command queue barrier will not |
| launch until all commands prior to the barrier are complete.</p> |
| </li> |
| <li> |
| <p>The second source of prerequisites is dependencies between commands |
| expressed through events. |
| A command may include an optional list of events. |
| The command will wait and not launch until all the events in the list |
| are in the state CL COMPLETE. |
| By this mechanism, event objects define order constraints between |
| commands and coordinate execution between the host and one or more |
| devices.</p> |
| </li> |
| <li> |
| <p>The third source of prerequisites can be the presence of non-trivial C |
| initializers or C constructors for program scope global variables. |
| In this case, OpenCL C/C compiler shall generate program |
| initialization kernels that perform C initialization or C++ |
| construction. |
| These kernels must be executed by OpenCL runtime on a device before any |
| kernel from the same program can be executed on the same device. |
| The ND-range for any program initialization kernel is (1,1,1). |
| When multiple programs are linked together, the order of execution of |
| program initialization kernels that belong to different programs is |
| undefined.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Program clean up may result in the execution of one or more program clean up |
| kernels by the OpenCL runtime. |
| This is due to the presence of non-trivial C++ destructors for |
| program scope variables. |
| The ND-range for executing any program clean up kernel is (1,1,1). |
| The order of execution of clean up kernels from different programs (that are |
| linked together) is undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Note that C initializers, C constructors, or C destructors for program |
| scope variables cannot use pointers to coarse grain and fine grain SVM |
| allocations.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A command may be submitted to a device and yet have no visible side effects |
| outside of waiting on and satisfying event dependences. |
| Examples include markers, kernels executed over ranges of no work-items or |
| copy operations with zero sizes. |
| Such commands may pass directly from the <em>ready</em> state to the <em>ended</em> state.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Command execution can be blocking or non-blocking. |
| Consider a sequence of OpenCL commands. |
| For blocking commands, the OpenCL API functions that enqueue commands don’t |
| return until the command has completed. |
| Alternatively, OpenCL functions that enqueue non-blocking commands return |
| immediately and require that a programmer defines dependencies between |
| enqueued commands to ensure that enqueued commands are not launched before |
| needed resources are available. |
| In both cases, the actual execution of the command may occur asynchronously |
| with execution of the host program.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Commands within a single command-queue execute relative to each other in one |
| of two modes:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>In-order Execution</strong>: Commands and any side effects associated with |
| commands appear to the OpenCL application as if they execute in the same |
| order they are enqueued to a command-queue.</p> |
| </li> |
| <li> |
| <p><strong>Out-of-order Execution</strong>: Commands execute in any order constrained only |
| by explicit synchronization points (e.g. through command queue barriers) |
| or explicit dependencies on events.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Multiple command-queues can be present within a single context. |
| Multiple command-queues execute commands independently. |
| Event objects visible to the host program can be used to define |
| synchronization points between commands in multiple command queues. |
| If such synchronization points are established between commands in multiple |
| command-queues, an implementation must assure that the command-queues |
| progress concurrently and correctly account for the dependencies established |
| by the synchronization points. |
| For a detailed explanation of synchronization points, see |
| <a href="#execution-model-sync">Execution Model: Synchronization</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The core of the OpenCL execution model is defined by how the kernels |
| execute. |
| When a kernel-enqueue command submits a kernel for execution, an index space |
| is defined. |
| The kernel, the argument values associated with the arguments to the kernel, |
| and the parameters that define the index space define a <em>kernel-instance</em>. |
| When a kernel-instance executes on a device, the kernel function executes |
| for each point in the defined index space. |
| Each of these executing kernel functions is called a <em>work-item</em>. |
| The work-items associated with a given kernel-instance are managed by the |
| device in groups called <em>work-groups</em>. |
| These work-groups define a coarse grained decomposition of the Index space. |
| Work-groups are further divided into <em>sub-groups</em>, which provide an |
| additional level of control over execution.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Work-items have a global ID based on their coordinates within the Index |
| space. |
| They can also be defined in terms of their work-group and the local ID |
| within a work-group. |
| The details of this mapping are described in the following section.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="_execution_model_mapping_work_items_onto_an_ndrange">3.2.1. Execution Model: Mapping work-items onto an NDRange</h4> |
| <div class="paragraph"> |
| <p>The index space supported by OpenCL is called an NDRange. |
| An NDRange is an N-dimensional index space, where N is one, two or three. |
| The NDRange is decomposed into work-groups forming blocks that cover the |
| Index space. |
| An NDRange is defined by three integer arrays of length N:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>The extent of the index space (or global size) in each dimension.</p> |
| </li> |
| <li> |
| <p>An offset index F indicating the initial value of the indices in each |
| dimension (zero by default).</p> |
| </li> |
| <li> |
| <p>The size of a work-group (local size) in each dimension.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Each work-items global ID is an N-dimensional tuple. |
| The global ID components are values in the range from F, to F plus the |
| number of elements in that dimension minus one.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If a kernel is created from OpenCL 2.0 or SPIR-V, the size of work-groups in |
| an NDRange (the local size) need not be the same for all work-groups. |
| In this case, any single dimension for which the global size is not |
| divisible by the local size will be partitioned into two regions. |
| One region will have work-groups that have the same number of work items as |
| was specified for that dimension by the programmer (the local size). |
| The other region will have work-groups with less than the number of work |
| items specified by the local size parameter in that dimension (the |
| <em>remainder work-groups</em>). |
| Work-group sizes could be non-uniform in multiple dimensions, potentially |
| producing work-groups of up to 4 different sizes in a 2D range and 8 |
| different sizes in a 3D range.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Each work-item is assigned to a work-group and given a local ID to represent |
| its position within the work-group. |
| A work-item’s local ID is an N-dimensional tuple with components in the |
| range from zero to the size of the work-group in that dimension minus one.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Work-groups are assigned IDs similarly. |
| The number of work-groups in each dimension is not directly defined but is |
| inferred from the local and global NDRanges provided when a kernel-instance |
| is enqueued. |
| A work-group’s ID is an N-dimensional tuple with components in the range 0 |
| to the ceiling of the global size in that dimension divided by the local |
| size in the same dimension. |
| As a result, the combination of a work-group ID and the local-ID within a |
| work-group uniquely defines a work-item. |
| Each work-item is identifiable in two ways; in terms of a global index, and |
| in terms of a work-group index plus a local index within a work group.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example, consider the <a href="#index-space-image">2-dimensional index space</a> |
| shown below. |
| We input the index space for the work-items (G<sub>x</sub>, G<sub>y</sub>), the size of each |
| work-group (S<sub>x</sub>, S<sub>y</sub>) and the global ID offset (F<sub>x</sub>, F<sub>y</sub>). |
| The global indices define an G<sub>x</sub>by G<sub>y</sub> index space where the total number |
| of work-items is the product of G<sub>x</sub> and G<sub>y</sub>. |
| The local indices define an S<sub>x</sub> by S<sub>y</sub> index space where the number of |
| work-items in a single work-group is the product of S<sub>x</sub> and S<sub>y</sub>. |
| Given the size of each work-group and the total number of work-items we can |
| compute the number of work-groups. |
| A 2-dimensional index space is used to uniquely identify a work-group. |
| Each work-item is identified by its global ID (<em>g</em><sub>x</sub>, <em>g</em><sub>y</sub>) or by the |
| combination of the work-group ID (<em>w</em><sub>x</sub>, <em>w</em><sub>y</sub>), the size of each |
| work-group (S<sub>x</sub>,S<sub>y</sub>) and the local ID (s<sub>x</sub>, s<sub>y</sub>) inside the work-group |
| such that</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p>(g<sub>x</sub> , g<sub>y</sub>) = (w<sub>x</sub> S<sub>x</sub> + s<sub>x</sub> + F<sub>x</sub>, w<sub>y</sub> S<sub>y</sub> + s<sub>y</sub> + F<sub>y</sub>)</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>The number of work-groups can be computed as:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p>(W<sub>x</sub>, W<sub>y</sub>) = (ceil(G<sub>x</sub> / S<sub>x</sub>), ceil(G<sub>y</sub> / S<sub>y</sub>))</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>Given a global ID and the work-group size, the work-group ID for a work-item |
| is computed as:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p>(w<sub>x</sub>, w<sub>y</sub>) = ( (g<sub>x</sub> s<sub>x</sub> F<sub>x</sub>) / S<sub>x</sub>, (g<sub>y</sub> s<sub>y</sub> F<sub>y</sub>) / S<sub>y</sub> )</p> |
| </dd> |
| </dl> |
| </div> |
| <div id="index-space-image" class="imageblock" style="text-align: center"> |
| <div class="content"> |
| <img src="data:image/jpg;base64,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/wDwlWiHSbfVFv42sriN5IpVBIZVBLHpngA0AV/7N8T/APQw2v8A4Lx/8XR/Zvif/oYbX/wXj/4ukTx14ck0ufUU1EG3gkWOX904dGbhQUxu5zxxzWlo+t6dr1o11ptyJ4lcxt8pUqw7EEAg8jrQBnf2b4n/AOhhtf8AwXj/AOLo/s3xP/0MNr/4Lx/8XXQ0UAc9/Zvif/oYbX/wXj/4uj+zfE//AEMNr/4Lx/8AF10NRW9zFdRs8TEqrshypHKnB6+4oAw/7N8T/wDQw2v/AILx/wDF0f2b4n/6GG1/8F4/+LroaxNN8W6Jq+pPp9leiW4UMQNjKsgU4YoxGGweDgmgCH+zfE//AEMNr/4Lx/8AF1V1HR/FNxp1xCuvW7s6FQq2nlk/Rg+V+tdXRQB5poeleJdJ8X+H4fEeuRao5hvPJ2xYaMYTgvwX/IV6XUbQQvPHM8SNLGCEcqCyg9cHtnAqSgAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAIrkFrSYKCWKMAB9K8ifw/rml21jBBp08umS6c1yY44yZLe58kK8e3/aPIHrmvYqKAPLr/T9S8Sa62tW1hqOn25extkeSHZO2ybe8pRgcBQcAsPWs7XdI1WCPUrEWmoXzvqMsovXs2laXdAnl4ClVyDuUP0Xb0ya9iooA8gk0S+XSrrV0tL+G+nuLjzJJWaN/IMQ4+Y4UEg496zL2xkv5b0aLp+o22mpcui2pt2leOZoI9h2bwY++CeFJyQM17dPBFdW8kE8aSwyKVdHGQwPUEVBp2l2OkWxt9PtIraEsXKxLgFj1J9TQBxXjqyv5U0Nktrq5mhUgqkLSo0nycMVIMbcHEnQc561i3VlfXPiNIW0fU4rqD7VLbXyQOVeZ3kESmQcKig7ueMlfSvWqKAPN/h1pOpQaZqcN0t1C0tvHE3n27Q/vwrB2GWJY5Iy44btTdIv9UtLnRom0nVo4dKs5Ir6E2ieUGSPAMTkZYsRng4I6816VUF7BJdWM8ENw1vJIhVZlGSme496GBT0PXbLxFYG+08yPalyiSsu0SY6lfUZ4+oNadZPh3QIPDWljTbSaWS0RyYUlOTGp5257jOT+Na1ABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAH//2Q==" alt="index space"> |
| </div> |
| <div class="title">Figure 3. An example of an NDRange index space showing work-items, their global IDs and their mapping onto the pair of work-group and local IDs. In this case, we assume that in each dimension, the size of the work-group evenly divides the global NDRange size (i.e. all work-groups have the same size) and that the offset is equal to zero.</div> |
| </div> |
| <div class="paragraph"> |
| <p>Within a work-group work-items may be divided into sub-groups. |
| The mapping of work-items to sub-groups is implementation-defined and may be |
| queried at runtime. |
| While sub-groups may be used in multi-dimensional work-groups, each |
| sub-group is 1-dimensional and any given work-item may query which sub-group |
| it is a member of.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Work items are mapped into sub-groups through a combination of compile-time |
| decisions and the parameters of the dispatch. |
| The mapping to sub-groups is invariant for the duration of a kernels |
| execution, across dispatches of a given kernel with the same work-group |
| dimensions, between dispatches and query operations consistent with the |
| dispatch parameterization, and from one work-group to another within the |
| dispatch (excluding the trailing edge work-groups in the presence of |
| non-uniform work-group sizes). |
| In addition, all sub-groups within a work-group will be the same size, apart |
| from the sub-group with the maximum index which may be smaller if the size |
| of the work-group is not evenly divisible by the size of the sub-groups.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In the degenerate case, a single sub-group must be supported for each |
| work-group. |
| In this situation all sub-group scope functions are equivalent to their |
| work-group level equivalents.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_execution_model_execution_of_kernel_instances">3.2.2. Execution Model: Execution of kernel-instances</h4> |
| <div class="paragraph"> |
| <p>The work carried out by an OpenCL program occurs through the execution of |
| kernel-instances on compute devices. |
| To understand the details of OpenCLs execution model, we need to consider |
| how a kernel object moves from the kernel-enqueue command, into a |
| command-queue, executes on a device, and completes.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A kernel-object is defined from a function within the program object and a |
| collection of arguments connecting the kernel to a set of argument values. |
| The host program enqueues a kernel-object to the command queue along with |
| the NDRange, and the work-group decomposition. |
| These define a <em>kernel-instance</em>. |
| In addition, an optional set of events may be defined when the kernel is |
| enqueued. |
| The events associated with a particular kernel-instance are used to |
| constrain when the kernel-instance is launched with respect to other |
| commands in the queue or to commands in other queues within the same |
| context.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A kernel-instance is submitted to a device. |
| For an in-order command queue, the kernel instances appear to launch and |
| then execute in that same order; where we use the term appear to emphasize |
| that when there are no dependencies between commands and hence differences |
| in the order that commands execute cannot be observed in a program, an |
| implementation can reorder commands even in an in-order command queue. |
| For an out of order command-queue, kernel-instances wait to be launched |
| until:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Synchronization commands enqueued prior to the kernel-instance are |
| satisfied.</p> |
| </li> |
| <li> |
| <p>Each of the events in an optional event list defined when the |
| kernel-instance was enqueued are set to CL_COMPLETE.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Once these conditions are met, the kernel-instance is launched and the |
| work-groups associated with the kernel-instance are placed into a pool of |
| ready to execute work-groups. |
| This pool is called a <em>work-pool</em>. |
| The work-pool may be implemented in any manner as long as it assures that |
| work-groups placed in the pool will eventually execute. |
| The device schedules work-groups from the work-pool for execution on the |
| compute units of the device. |
| The kernel-enqueue command is complete when all work-groups associated with |
| the kernel-instance end their execution, updates to global memory associated |
| with a command are visible globally, and the device signals successful |
| completion by setting the event associated with the kernel-enqueue command |
| to CL_COMPLETE.</p> |
| </div> |
| <div class="paragraph"> |
| <p>While a command-queue is associated with only one device, a single device |
| may be associated with multiple command-queues all feeding into the single |
| work-pool. |
| A device may also be associated with command queues associated with |
| different contexts within the same platform, again all feeding into the |
| single work-pool. |
| The device will pull work-groups from the work-pool and execute them on one |
| or several compute units in any order; possibly interleaving execution of |
| work-groups from multiple commands. |
| A conforming implementation may choose to serialize the work-groups so a |
| correct algorithm cannot assume that work-groups will execute in parallel. |
| There is no safe and portable way to synchronize across the independent |
| execution of work-groups since once in the work-pool, they can execute in |
| any order.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The work-items within a single sub-group execute concurrently but not |
| necessarily in parallel (i.e. they are not guaranteed to make independent |
| forward progress). |
| Therefore, only high-level synchronization constructs (e.g. sub-group |
| functions such as barriers) that apply to all the work-items in a sub-group |
| are well defined and included in OpenCL.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Sub-groups execute concurrently within a given work-group and with |
| appropriate device support (see <a href="#platform-querying-devices">Querying |
| Devices</a>), may make independent forward progress with respect to each |
| other, with respect to host threads and with respect to any entities |
| external to the OpenCL system but running on an OpenCL device, even in the |
| absence of work-group barrier operations. |
| In this situation, sub-groups are able to internally synchronize using |
| barrier operations without synchronizing with each other and may perform |
| operations that rely on runtime dependencies on operations other sub-groups |
| perform.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The work-items within a single work-group execute concurrently but are only |
| guaranteed to make independent progress in the presence of sub-groups and |
| device support. |
| In the absence of this capability, only high-level synchronization |
| constructs (e.g. work-group functions such as barriers) that apply to all |
| the work-items in a work-group are well defined and included in OpenCL for |
| synchronization within the work-group.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In the absence of synchronization functions (e.g. a barrier), work-items |
| within a sub-group may be serialized. |
| In the presence of sub -group functions, work-items within a sub -group may |
| be serialized before any given sub -group function, between dynamically |
| encountered pairs of sub-group functions and between a work-group function |
| and the end of the kernel.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In the absence of independent forward progress of constituent sub-groups, |
| work-items within a work-group may be serialized before, after or between |
| work-group synchronization functions.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="device-side-enqueue">3.2.3. Execution Model: Device-side enqueue</h4> |
| <div class="paragraph"> |
| <p>Algorithms may need to generate additional work as they execute. |
| In many cases, this additional work cannot be determined statically; so the |
| work associated with a kernel only emerges at runtime as the kernel-instance |
| executes. |
| This capability could be implemented in logic running within the host |
| program, but involvement of the host may add significant overhead and/or |
| complexity to the application control flow. |
| A more efficient approach would be to nest kernel-enqueue commands from |
| inside other kernels. |
| This <strong>nested parallelism</strong> can be realized by supporting the enqueuing of |
| kernels on a device without direct involvement by the host program; |
| so-called <strong>device-side enqueue</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Device-side kernel-enqueue commands are similar to host-side kernel-enqueue |
| commands. |
| The kernel executing on a device (the <strong>parent kernel</strong>) enqueues a |
| kernel-instance (the <strong>child kernel</strong>) to a device-side command queue. |
| This is an out-of-order command-queue and follows the same behavior as the |
| out-of-order command-queues exposed to the host program. |
| Commands enqueued to a device side command-queue generate and use events to |
| enforce order constraints just as for the command-queue on the host. |
| These events, however, are only visible to the parent kernel running on the |
| device. |
| When these prerequisite events take on the value CL_COMPLETE, the |
| work-groups associated with the child kernel are launched into the devices |
| work pool. |
| The device then schedules them for execution on the compute units of the |
| device. |
| Child and parent kernels execute asynchronously. |
| However, a parent will not indicate that it is complete by setting its event |
| to CL_COMPLETE until all child kernels have ended execution and have |
| signaled completion by setting any associated events to the value |
| CL_COMPLETE. |
| Should any child kernel complete with an event status set to a negative |
| value (i.e. abnormally terminate), the parent kernel will abnormally |
| terminate and propagate the childs negative event value as the value of the |
| parents event. |
| If there are multiple children that have an event status set to a negative |
| value, the selection of which childs negative event value is propagated is |
| implementation-defined.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="execution-model-sync">3.2.4. Execution Model: Synchronization</h4> |
| <div class="paragraph"> |
| <p>Synchronization refers to mechanisms that constrain the order of execution |
| between two or more units of execution. |
| Consider the following three domains of synchronization in OpenCL:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Work-group synchronization: Constraints on the order of execution for |
| work-items in a single work-group</p> |
| </li> |
| <li> |
| <p>Sub-group synchronization: Constraints on the order of execution for |
| work-items in a single sub-group</p> |
| </li> |
| <li> |
| <p>Command synchronization: Constraints on the order of commands launched |
| for execution</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Synchronization across all work-items within a single work-group is carried |
| out using a <em>work-group function</em>. |
| These functions carry out collective operations across all the work-items in |
| a work-group. |
| Available collective operations are: barrier, reduction, broadcast, prefix |
| sum, and evaluation of a predicate. |
| A work-group function must occur within a converged control flow; i.e. all |
| work-items in the work-group must encounter precisely the same work-group |
| function. |
| For example, if a work-group function occurs within a loop, the work-items |
| must encounter the same work-group function in the same loop iterations. |
| All the work-items of a work-group must execute the work-group function and |
| complete reads and writes to memory before any are allowed to continue |
| execution beyond the work-group function. |
| Work-group functions that apply between work-groups are not provided in |
| OpenCL since OpenCL does not define forward-progress or ordering relations |
| between work-groups, hence collective synchronization operations are not |
| well defined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Synchronization across all work-items within a single sub-group is carried |
| out using a <em>sub-group function</em>. |
| These functions carry out collective operations across all the work-items in |
| a sub-group. |
| Available collective operations are: barrier, reduction, broadcast, prefix |
| sum, and evaluation of a predicate. |
| A sub-group function must occur within a converged control flow; i.e. all |
| work-items in the sub-group must encounter precisely the same sub-group |
| function. |
| For example, if a work-group function occurs within a loop, the work-items |
| must encounter the same sub-group function in the same loop iterations. |
| All the work-items of a sub-group must execute the sub-group function and |
| complete reads and writes to memory before any are allowed to continue |
| execution beyond the sub-group function. |
| Synchronization between sub-groups must either be performed using work-group |
| functions, or through memory operations. |
| Using memory operations for sub-group synchronization should be used |
| carefully as forward progress of sub-groups relative to each other is only |
| supported optionally by OpenCL implementations.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Command synchronization is defined in terms of distinct <strong>synchronization |
| points</strong>. |
| The synchronization points occur between commands in host command-queues and |
| between commands in device-side command-queues. |
| The synchronization points defined in OpenCL include:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>Launching a command:</strong> A kernel-instance is launched onto a device after |
| all events that kernel is waiting-on have been set to CL_COMPLETE.</p> |
| </li> |
| <li> |
| <p><strong>Ending a command:</strong> Child kernels may be enqueued such that they wait |
| for the parent kernel to reach the <em>end</em> state before they can be |
| launched. |
| In this case, the ending of the parent command defines a synchronization |
| point.</p> |
| </li> |
| <li> |
| <p><strong>Completion of a command:</strong> A kernel-instance is complete after all of |
| the work-groups in the kernel and all of its child kernels have |
| completed. |
| This is signaled to the host, a parent kernel or other kernels within |
| command queues by setting the value of the event associated with a |
| kernel to CL_COMPLETE.</p> |
| </li> |
| <li> |
| <p><strong>Blocking Commands:</strong> A blocking command defines a synchronization point |
| between the unit of execution that calls the blocking API function and |
| the enqueued command reaching the complete state.</p> |
| </li> |
| <li> |
| <p><strong>Command-queue barrier:</strong> The command-queue barrier ensures that all |
| previously enqueued commands have completed before subsequently enqueued |
| commands can be launched.</p> |
| </li> |
| <li> |
| <p><strong>clFinish:</strong> This function blocks until all previously enqueued commands |
| in the command queue have completed after which <strong>clFinish</strong> defines a |
| synchronization point and the <strong>clFinish</strong> function returns.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>A synchronization point between a pair of commands (A and B) assures that |
| results of command A happens-before command B is launched. |
| This requires that any updates to memory from command A complete and are |
| made available to other commands before the synchronization point completes. |
| Likewise, this requires that command B waits until after the synchronization |
| point before loading values from global memory. |
| The concept of a synchronization point works in a similar fashion for |
| commands such as a barrier that apply to two sets of commands. |
| All the commands prior to the barrier must complete and make their results |
| available to following commands. |
| Furthermore, any commands following the barrier must wait for the commands |
| prior to the barrier before loading values and continuing their execution.</p> |
| </div> |
| <div class="paragraph"> |
| <p>These <em>happens-before</em> relationships are a fundamental part of the OpenCL |
| memory model. |
| When applied at the level of commands, they are straightforward to define at |
| a language level in terms of ordering relationships between different |
| commands. |
| Ordering memory operations inside different commands, however, requires |
| rules more complex than can be captured by the high level concept of a |
| synchronization point. |
| These rules are described in detail in <a href="#memory-ordering-rules">Memory |
| Ordering Rules</a>.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_execution_model_categories_of_kernels">3.2.5. Execution Model: Categories of Kernels</h4> |
| <div class="paragraph"> |
| <p>The OpenCL execution model supports three types of kernels:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>OpenCL kernels</strong> are managed by the OpenCL API as kernel-objects |
| associated with kernel functions within program-objects. |
| OpenCL kernels are provided via a kernel language. |
| All OpenCL implementations must support OpenCL kernels supplied in the |
| standard SPIR-V intermediate language with the appropriate environment |
| specification, and the OpenCL C programming language defined in earlier |
| versions of the OpenCL specification. |
| Implementations must also support OpenCL kernels in SPIR-V intermediate |
| language. |
| SPIR-V binaries nay be generated from an OpenCL kernel language or by a |
| third party compiler from an alternative input.</p> |
| </li> |
| <li> |
| <p><strong>Native kernels</strong> are accessed through a host function pointer. |
| Native kernels are queued for execution along with OpenCL kernels on a |
| device and share memory objects with OpenCL kernels. |
| For example, these native kernels could be functions defined in |
| application code or exported from a library. |
| The ability to execute native kernels is optional within OpenCL and the |
| semantics of native kernels are implementation-defined. |
| The OpenCL API includes functions to query capabilities of a device(s) |
| and determine if this capability is supported.</p> |
| </li> |
| <li> |
| <p><strong>Built-in kernels</strong> are tied to particular device and are not built at |
| runtime from source code in a program object. |
| The common use of built in kernels is to expose fixed-function hardware |
| or firmware associated with a particular OpenCL device or custom device. |
| The semantics of a built-in kernel may be defined outside of OpenCL and |
| hence are implementation defined.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>All three types of kernels are manipulated through the OpenCL command queues |
| and must conform to the synchronization points defined in the OpenCL |
| execution model.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_memory_model">3.3. Memory Model</h3> |
| <div class="paragraph"> |
| <p>The OpenCL memory model describes the structure, contents, and behavior of |
| the memory exposed by an OpenCL platform as an OpenCL program runs. |
| The model allows a programmer to reason about values in memory as the host |
| program and multiple kernel-instances execute.</p> |
| </div> |
| <div class="paragraph"> |
| <p>An OpenCL program defines a context that includes a host, one or more |
| devices, command-queues, and memory exposed within the context. |
| Consider the units of execution involved with such a program. |
| The host program runs as one or more host threads managed by the operating |
| system running on the host (the details of which are defined outside of |
| OpenCL). |
| There may be multiple devices in a single context which all have access to |
| memory objects defined by OpenCL. |
| On a single device, multiple work-groups may execute in parallel with |
| potentially overlapping updates to memory. |
| Finally, within a single work-group, multiple work-items concurrently |
| execute, once again with potentially overlapping updates to memory.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The memory model must precisely define how the values in memory as seen from |
| each of these units of execution interact so a programmer can reason about |
| the correctness of OpenCL programs. |
| We define the memory model in four parts.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Memory regions: The distinct memories visible to the host and the |
| devices that share a context.</p> |
| </li> |
| <li> |
| <p>Memory objects: The objects defined by the OpenCL API and their |
| management by the host and devices.</p> |
| </li> |
| <li> |
| <p>Shared Virtual Memory: A virtual address space exposed to both the host |
| and the devices within a context.</p> |
| </li> |
| <li> |
| <p>Consistency Model: Rules that define which values are observed when |
| multiple units of execution load data from memory plus the atomic/fence |
| operations that constrain the order of memory operations and define |
| synchronization relationships.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="sect3"> |
| <h4 id="_memory_model_fundamental_memory_regions">3.3.1. Memory Model: Fundamental Memory Regions</h4> |
| <div class="paragraph"> |
| <p>Memory in OpenCL is divided into two parts.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>Host Memory:</strong> The memory directly available to the host. |
| The detailed behavior of host memory is defined outside of OpenCL. |
| Memory objects move between the Host and the devices through functions |
| within the OpenCL API or through a shared virtual memory interface.</p> |
| </li> |
| <li> |
| <p><strong>Device Memory:</strong> Memory directly available to kernels executing on |
| OpenCL devices.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Device memory consists of four named address spaces or <em>memory regions</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>Global Memory:</strong> This memory region permits read/write access to all |
| work-items in all work-groups running on any device within a context. |
| Work-items can read from or write to any element of a memory object. |
| Reads and writes to global memory may be cached depending on the |
| capabilities of the device.</p> |
| </li> |
| <li> |
| <p><strong>Constant Memory</strong>: A region of global memory that remains constant |
| during the execution of a kernel-instance. |
| The host allocates and initializes memory objects placed into constant |
| memory.</p> |
| </li> |
| <li> |
| <p><strong>Local Memory</strong>: A memory region local to a work-group. |
| This memory region can be used to allocate variables that are shared by |
| all work-items in that work-group.</p> |
| </li> |
| <li> |
| <p><strong>Private Memory</strong>: A region of memory private to a work-item. |
| Variables defined in one work-items private memory are not visible to |
| another work-item.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The <a href="#memory-regions-image">memory regions</a> and their relationship to the |
| OpenCL Platform model are summarized below. |
| Local and private memories are always associated with a particular device. |
| The global and constant memories, however, are shared between all devices |
| within a given context. |
| An OpenCL device may include a cache to support efficient access to these |
| shared memories.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To understand memory in OpenCL, it is important to appreciate the |
| relationships between these named address spaces. |
| The four named address spaces available to a device are disjoint meaning |
| they do not overlap. |
| This is a logical relationship, however, and an implementation may choose to |
| let these disjoint named address spaces share physical memory.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Programmers often need functions callable from kernels where the pointers |
| manipulated by those functions can point to multiple named address spaces. |
| This saves a programmer from the error-prone and wasteful practice of |
| creating multiple copies of functions; one for each named address space. |
| Therefore the global, local and private address spaces belong to a single |
| <em>generic address space</em>. |
| This is closely modeled after the concept of a generic address space used in |
| the embedded C standard (ISO/IEC 9899:1999). |
| Since they all belong to a single generic address space, the following |
| properties are supported for pointers to named address spaces in device |
| memory:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>A pointer to the generic address space can be cast to a pointer to a |
| global, local or private address space</p> |
| </li> |
| <li> |
| <p>A pointer to a global, local or private address space can be cast to a |
| pointer to the generic address space.</p> |
| </li> |
| <li> |
| <p>A pointer to a global, local or private address space can be implicitly |
| converted to a pointer to the generic address space, but the converse is |
| not allowed.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The constant address space is disjoint from the generic address space.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The addresses of memory associated with memory objects in Global memory are |
| not preserved between kernel instances, between a device and the host, and |
| between devices. |
| In this regard global memory acts as a global pool of memory objects rather |
| than an address space. |
| This restriction is relaxed when shared virtual memory (SVM) is used.</p> |
| </div> |
| <div class="paragraph"> |
| <p>SVM causes addresses to be meaningful between the host and all of the |
| devices within a context hence supporting the use of pointer based data |
| structures in OpenCL kernels. |
| It logically extends a portion of the global memory into the host address |
| space giving work-items access to the host address space. |
| On platforms with hardware support for a shared address space between the |
| host and one or more devices, SVM may also provide a more efficient way to |
| share data between devices and the host. |
| Details about SVM are presented in <a href="#shared-virtual-memory">Shared Virtual |
| Memory</a>.</p> |
| </div> |
| <div id="memory-regions-image" class="imageblock" style="text-align: center"> |
| <div class="content"> |
| <img src="data:image/jpg;base64,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" alt="memory regions"> |
| </div> |
| <div class="title">Figure 4. The named address spaces exposed in an OpenCL Platform. Global and Constant memories are shared between the one or more devices within a context, while local and private memories are associated with a single device. Each device may include an optional cache to support efficient access to their view of the global and constant address spaces.</div> |
| </div> |
| <div class="paragraph"> |
| <p>A programmer may use the features of the <a href="#memory-consistency-model">memory |
| consistency model</a> to manage safe access to global memory from multiple |
| work-items potentially running on one or more devices. |
| In addition, when using shared virtual memory (SVM), the memory consistency |
| model may also be used to ensure that host threads safely access memory |
| locations in the shared memory region.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_memory_model_memory_objects">3.3.2. Memory Model: Memory Objects</h4> |
| <div class="paragraph"> |
| <p>The contents of global memory are <em>memory objects</em>. |
| A memory object is a handle to a reference counted region of global memory. |
| Memory objects use the OpenCL type <em>cl_mem</em> and fall into three distinct |
| classes.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>Buffer</strong>: A memory object stored as a block of contiguous memory and |
| used as a general purpose object to hold data used in an OpenCL program. |
| The types of the values within a buffer may be any of the built in types |
| (such as int, float), vector types, or user-defined structures. |
| The buffer can be manipulated through pointers much as one would with |
| any block of memory in C.</p> |
| </li> |
| <li> |
| <p><strong>Image</strong>: An image memory object holds one, two or three dimensional |
| images. |
| The formats are based on the standard image formats used in graphics |
| applications. |
| An image is an opaque data structure managed by functions defined in the |
| OpenCL API. |
| To optimize the manipulation of images stored in the texture memories |
| found in many GPUs, OpenCL kernels have traditionally been disallowed |
| from both reading and writing a single image. |
| In OpenCL 2.0, however, we have relaxed this restriction by providing |
| synchronization and fence operations that let programmers properly |
| synchronize their code to safely allow a kernel to read and write a |
| single image.</p> |
| </li> |
| <li> |
| <p><strong>Pipe</strong>: The <em>pipe</em> memory object conceptually is an ordered sequence of |
| data items. |
| A pipe has two endpoints: a write endpoint into which data items are |
| inserted, and a read endpoint from which data items are removed. |
| At any one time, only one kernel instance may write into a pipe, and |
| only one kernel instance may read from a pipe. |
| To support the producer consumer design pattern, one kernel instance |
| connects to the write endpoint (the producer) while another kernel |
| instance connects to the reading endpoint (the consumer).</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Memory objects are allocated by host APIs. |
| The host program can provide the runtime with a pointer to a block of |
| continuous memory to hold the memory object when the object is created |
| (CL_MEM_USE_HOST_PTR). |
| Alternatively, the physical memory can be managed by the OpenCL runtime and |
| not be directly accessible to the host program.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Allocation and access to memory objects within the different memory regions |
| varies between the host and work-items running on a device. |
| This is summarized in the <a href="#memory-regions-table">Memory Regions</a> table, |
| which describes whether the kernel or the host can allocate from a memory |
| region, the type of allocation (static at compile time vs. |
| dynamic at runtime) and the type of access allowed (i.e. whether the kernel |
| or the host can read and/or write to a memory region).</p> |
| </div> |
| <table id="memory-regions-table" class="tableblock frame-all grid-all" style="width: 80%;"> |
| <caption class="title">Table 1. Memory Regions</caption> |
| <colgroup> |
| <col style="width: 20%;"> |
| <col style="width: 20%;"> |
| <col style="width: 20%;"> |
| <col style="width: 20%;"> |
| <col style="width: 20%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"></th> |
| <th class="tableblock halign-left valign-top">Global</th> |
| <th class="tableblock halign-left valign-top">Constant</th> |
| <th class="tableblock halign-left valign-top">Local</th> |
| <th class="tableblock halign-left valign-top">Private</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top" rowspan="2"><p class="tableblock">Host</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Dynamic Allocation</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Dynamic Allocation</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Dynamic Allocation</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">No Allocation</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Read/Write access to buffers and images but not pipes</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Read/Write access</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">No access</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">No access</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top" rowspan="2"><p class="tableblock">Kernel</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Static Allocation for program scope variables</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Static Allocation</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Static Allocation.</p> |
| <p class="tableblock"> Dynamic allocation for child kernel</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Static Allocation</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Read/Write access</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Read-only access</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Read/Write access.</p> |
| <p class="tableblock"> No access to child’s local memory.</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Read/Write access</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="sidebarblock"> |
| <div class="content"> |
| <div class="title">Caption</div> |
| <div class="paragraph"> |
| <p>The <a href="#memory-regions-table">Memory Regions</a> table shows the different |
| memory regions in OpenCL and how memory objects are allocated and accessed |
| by the host and by an executing instance of a kernel. |
| For the case of kernels, we distinguish between the behavior of local memory |
| with respect to a kernel (self) and its child kernels.</p> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Once allocated, a memory object is made available to kernel-instances |
| running on one or more devices. |
| In addition to <a href="#shared-virtual-memory">Shared Virtual Memory</a>, there are |
| three basic ways to manage the contents of buffers between the host and |
| devices.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>Read/Write/Fill commands</strong>: The data associated with a memory object is |
| explicitly read and written between the host and global memory regions |
| using commands enqueued to an OpenCL command queue.</p> |
| </li> |
| <li> |
| <p><strong>Map/Unmap commands</strong>: Data from the memory object is mapped into a |
| contiguous block of memory accessed through a host accessible pointer. |
| The host program enqueues a <em>map</em> command on block of a memory object |
| before it can be safely manipulated by the host program. |
| When the host program is finished working with the block of memory, the |
| host program enqueues an <em>unmap</em> command to allow a kernel-instance to |
| safely read and/or write the buffer.</p> |
| </li> |
| <li> |
| <p><strong>Copy commands:</strong> The data associated with a memory object is copied |
| between two buffers, each of which may reside either on the host or on |
| the device.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>With Read/Write/Map, the commands |
| can be blocking or non-blocking operations. |
| The OpenCL function call for a blocking memory transfer returns once the |
| command (memory transfer) has completed. At this point the associated memory |
| resources on the host can be safely reused, and following operations on the host are |
| guaranteed that the transfer has already completed. |
| For a non-blocking memory transfer, the OpenCL function call returns as soon |
| as the command is enqueued.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Memory objects are bound to a context and hence can appear in multiple |
| kernel-instances running on more than one physical device. |
| The OpenCL platform must support a large range of hardware platforms |
| including systems that do not support a single shared address space in |
| hardware; hence the ways memory objects can be shared between |
| kernel-instances is restricted. |
| The basic principle is that multiple read operations on memory objects from |
| multiple kernel-instances that overlap in time are allowed, but mixing |
| overlapping reads and writes into the same memory objects from different |
| kernel instances is only allowed when fine grained synchronization is used |
| with <a href="#shared-virtual-memory">Shared Virtual Memory</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When global memory is manipulated by multiple kernel-instances running on |
| multiple devices, the OpenCL runtime system must manage the association of |
| memory objects with a given device. |
| In most cases the OpenCL runtime will implicitly associate a memory object |
| with a device. |
| A kernel instance is naturally associated with the command queue to which |
| the kernel was submitted. |
| Since a command-queue can only access a single device, the queue uniquely |
| defines which device is involved with any given kernel-instance; hence |
| defining a clear association between memory objects, kernel-instances and |
| devices. |
| Programmers may anticipate these associations in their programs and |
| explicitly manage association of memory objects with devices in order to |
| improve performance.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="shared-virtual-memory">3.3.3. Memory Model: Shared Virtual Memory</h4> |
| <div class="paragraph"> |
| <p>OpenCL extends the global memory region into the host memory region through |
| a shared virtual memory (SVM) mechanism. |
| There are three types of SVM in OpenCL</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>Coarse-Grained buffer SVM</strong>: Sharing occurs at the granularity of |
| regions of OpenCL buffer memory objects. |
| Consistency is enforced at synchronization points and with map/unmap |
| commands to drive updates between the host and the device. |
| This form of SVM is similar to non-SVM use of memory; however, it lets |
| kernel-instances share pointer-based data structures (such as |
| linked-lists) with the host program. |
| Program scope global variables are treated as per-device coarse-grained |
| SVM for addressing and sharing purposes.</p> |
| </li> |
| <li> |
| <p><strong>Fine-Grained buffer SVM</strong>: Sharing occurs at the granularity of |
| individual loads/stores into bytes within OpenCL buffer memory objects. |
| Loads and stores may be cached. |
| This means consistency is guaranteed at synchronization points. |
| If the optional OpenCL atomics are supported, they can be used to |
| provide fine-grained control of memory consistency.</p> |
| </li> |
| <li> |
| <p><strong>Fine-Grained system SVM</strong>: Sharing occurs at the granularity of |
| individual loads/stores into bytes occurring anywhere within the host |
| memory. |
| Loads and stores may be cached so consistency is guaranteed at |
| synchronization points. |
| If the optional OpenCL atomics are supported, they can be used to |
| provide fine-grained control of memory consistency.</p> |
| </li> |
| </ul> |
| </div> |
| <table id="svm-summary-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 2. A summary of shared virtual memory (SVM) options in OpenCL</caption> |
| <colgroup> |
| <col style="width: 20%;"> |
| <col style="width: 20%;"> |
| <col style="width: 20%;"> |
| <col style="width: 20%;"> |
| <col style="width: 20%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-center valign-top"></th> |
| <th class="tableblock halign-center valign-top">Granularity of sharing</th> |
| <th class="tableblock halign-center valign-top">Memory Allocation</th> |
| <th class="tableblock halign-center valign-top">Mechanisms to enforce Consistency</th> |
| <th class="tableblock halign-center valign-top">Explicit updates between host and device</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-center valign-top"><p class="tableblock">Non-SVM buffers</p></td> |
| <td class="tableblock halign-center valign-top"><p class="tableblock">OpenCL Memory objects(buffer)</p></td> |
| <td class="tableblock halign-center valign-top"><p class="tableblock"><strong>clCreateBuffer</strong></p></td> |
| <td class="tableblock halign-center valign-top"><p class="tableblock">Host synchronization points on the same or between devices.</p></td> |
| <td class="tableblock halign-center valign-top"><p class="tableblock">yes, through Map and Unmap commands.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-center valign-top"><p class="tableblock">Coarse-Grained buffer SVM</p></td> |
| <td class="tableblock halign-center valign-top"><p class="tableblock">OpenCL Memory objects (buffer)</p></td> |
| <td class="tableblock halign-center valign-top"><p class="tableblock"><strong>clSVMAlloc</strong></p></td> |
| <td class="tableblock halign-center valign-top"><p class="tableblock">Host synchronization points between devices</p></td> |
| <td class="tableblock halign-center valign-top"><p class="tableblock">yes, through Map and Unmap commands.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-center valign-top"><p class="tableblock">Fine-Grained buffer SVM</p></td> |
| <td class="tableblock halign-center valign-top"><p class="tableblock">Bytes within OpenCL Memory objects (buffer)</p></td> |
| <td class="tableblock halign-center valign-top"><p class="tableblock"><strong>clSVMAlloc</strong></p></td> |
| <td class="tableblock halign-center valign-top"><p class="tableblock">Synchronization points plus atomics (if supported)</p></td> |
| <td class="tableblock halign-center valign-top"><p class="tableblock">No</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-center valign-top"><p class="tableblock">Fine-Grained system SVM</p></td> |
| <td class="tableblock halign-center valign-top"><p class="tableblock">Bytes within Host memory (system)</p></td> |
| <td class="tableblock halign-center valign-top"><p class="tableblock">Host memory allocation mechanisms (e.g. malloc)</p></td> |
| <td class="tableblock halign-center valign-top"><p class="tableblock">Synchronization points plus atomics (if supported)</p></td> |
| <td class="tableblock halign-center valign-top"><p class="tableblock">No</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>Coarse-Grained buffer SVM is required in the core OpenCL specification. |
| The two finer grained approaches are optional features in OpenCL. |
| The various SVM mechanisms to access host memory from the work-items |
| associated with a kernel instance are <a href="#svm-summary-table">summarized |
| above</a>.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="memory-consistency-model">3.3.4. Memory Model: Memory Consistency Model</h4> |
| <div class="paragraph"> |
| <p>The OpenCL memory model tells programmers what they can expect from an |
| OpenCL implementation; which memory operations are guaranteed to happen in |
| which order and which memory values each read operation will return. |
| The memory model tells compiler writers which restrictions they must follow |
| when implementing compiler optimizations; which variables they can cache in |
| registers and when they can move reads or writes around a barrier or atomic |
| operation. |
| The memory model also tells hardware designers about limitations on hardware |
| optimizations; for example, when they must flush or invalidate hardware |
| caches.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The memory consistency model in OpenCL is based on the memory model from the |
| ISO C11 programming language. |
| To help make the presentation more precise and self-contained, we include |
| modified paragraphs taken verbatim from the ISO C11 international standard. |
| When a paragraph is taken or modified from the C11 standard, it is |
| identified as such along with its original location in the <a href="#iso-c11">C11 |
| standard</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For programmers, the most intuitive model is the <em>sequential consistency</em> |
| memory model. |
| Sequential consistency interleaves the steps executed by each of the units |
| of execution. |
| Each access to a memory location sees the last assignment to that location |
| in that interleaving. |
| While sequential consistency is relatively straightforward for a programmer |
| to reason about, implementing sequential consistency is expensive. |
| Therefore, OpenCL implements a relaxed memory consistency model; i.e. it is |
| possible to write programs where the loads from memory violate sequential |
| consistency. |
| Fortunately, if a program does not contain any races and if the program only |
| uses atomic operations that utilize the sequentially consistent memory order |
| (the default memory ordering for OpenCL), OpenCL programs appear to execute |
| with sequential consistency.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Programmers can to some degree control how the memory model is relaxed by |
| choosing the memory order for synchronization operations. |
| The precise semantics of synchronization and the memory orders are formally |
| defined in <a href="#memory-ordering-rules">Memory Ordering Rules</a>. |
| Here, we give a high level description of how these memory orders apply to |
| atomic operations on atomic objects shared between units of execution. |
| OpenCL memory_order choices are based on those from the ISO C11 standard |
| memory model. |
| They are specified in certain OpenCL functions through the following |
| enumeration constants:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>memory_order_relaxed</strong>: implies no order constraints. |
| This memory order can be used safely to increment counters that are |
| concurrently incremented, but it doesn’t guarantee anything about the |
| ordering with respect to operations to other memory locations. |
| It can also be used, for example, to do ticket allocation and by expert |
| programmers implementing lock-free algorithms.</p> |
| </li> |
| <li> |
| <p><strong>memory_order_acquire</strong>: A synchronization operation (fence or atomic) |
| that has acquire semantics "acquires" side-effects from a release |
| operation that synchronises with it: if an acquire synchronises with a |
| release, the acquiring unit of execution will see all side-effects |
| preceding that release (and possibly subsequent side-effects.) As part |
| of carefully-designed protocols, programmers can use an "acquire" to |
| safely observe the work of another unit of execution.</p> |
| </li> |
| <li> |
| <p><strong>memory_order_release</strong>: A synchronization operation (fence or atomic |
| operation) that has release semantics "releases" side effects to an |
| acquire operation that synchronises with it. |
| All side effects that precede the release are included in the release. |
| As part of carefully-designed protocols, programmers can use a "release" |
| to make changes made in one unit of execution visible to other units of |
| execution.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| In general, no acquire must <em>always</em> synchronise with any particular |
| release. |
| However, synchronisation can be forced by certain executions. |
| See <a href="#memory-ordering-fence">Memory Order Rules: Fence Operations</a> for |
| detailed rules for when synchronisation must occur. |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>memory_order_acq_rel</strong>: A synchronization operation with acquire-release |
| semantics has the properties of both the acquire and release memory |
| orders. |
| It is typically used to order read-modify-write operations.</p> |
| </li> |
| <li> |
| <p><strong>memory_order_seq_cst</strong>: The loads and stores of each unit of execution |
| appear to execute in program (i.e., sequenced-before) order, and the |
| loads and stores from different units of execution appear to be simply |
| interleaved.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Regardless of which memory_order is specified, resolving constraints on |
| memory operations across a heterogeneous platform adds considerable overhead |
| to the execution of a program. |
| An OpenCL platform may be able to optimize certain operations that depend on |
| the features of the memory consistency model by restricting the scope of the |
| memory operations. |
| Distinct memory scopes are defined by the values of the memory_scope |
| enumeration constant:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>memory_scope_work_item</strong>: memory-ordering constraints only apply within |
| the work-item<sup>1</sup>.</p> |
| <div class="openblock"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">1</dt> |
| <dd> |
| <p>This value for memory_scope can only be used with atomic_work_item_fence |
| with flags set to CLK_IMAGE_MEM_FENCE.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| </li> |
| <li> |
| <p><strong>memory_scope_sub_group</strong>:memory-ordering constraints only apply within |
| the sub-group.</p> |
| </li> |
| <li> |
| <p><strong>memory_scope_work_group</strong>: memory-ordering constraints only apply to |
| work-items executing within a single work-group.</p> |
| </li> |
| <li> |
| <p><strong>memory_scope_device:</strong> memory-ordering constraints only apply to |
| work-items executing on a single device</p> |
| </li> |
| <li> |
| <p><strong>memory_scope_all_svm_devices</strong>: memory-ordering constraints apply to |
| work-items executing across multiple devices and (when using SVM) the |
| host. |
| A release performed with <strong>memory_scope_all_svm_devices</strong> to a buffer that |
| does not have the CL_MEM_SVM_ATOMICS flag set will commit to at least |
| <strong>memory_scope_device</strong> visibility, with full synchronization of the |
| buffer at a queue synchronization point (e.g. an OpenCL event).</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>These memory scopes define a hierarchy of visibilities when analyzing the |
| ordering constraints of memory operations. |
| For example if a programmer knows that a sequence of memory operations will |
| only be associated with a collection of work-items from a single work-group |
| (and hence will run on a single device), the implementation is spared the |
| overhead of managing the memory orders across other devices within the same |
| context. |
| This can substantially reduce overhead in a program. |
| All memory scopes are valid when used on global memory or local memory. |
| For local memory, all visibility is constrained to within a given work-group |
| and scopes wider than <strong>memory_scope_work_group</strong> carry no additional meaning.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In the following subsections (leading up to <a href="#opencl-framework">OpenCL |
| Framework</a>), we will explain the synchronization constructs and detailed |
| rules needed to use OpenCL’s relaxed memory models. |
| It is important to appreciate, however, that many programs do not benefit |
| from relaxed memory models. |
| Even expert programmers have a difficult time using atomics and fences to |
| write correct programs with relaxed memory models. |
| A large number of OpenCL programs can be written using a simplified memory |
| model. |
| This is accomplished by following these guidelines.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Write programs that manage safe sharing of global memory objects through |
| the synchronization points defined by the command queues.</p> |
| </li> |
| <li> |
| <p>Restrict low level synchronization inside work-groups to the work-group |
| functions such as barrier.</p> |
| </li> |
| <li> |
| <p>If you want sequential consistency behavior with system allocations or |
| fine-grain SVM buffers with atomics support, use only |
| <strong>memory_order_seq_cst</strong> operations with the scope |
| <strong>memory_scope_all_svm_devices</strong>.</p> |
| </li> |
| <li> |
| <p>If you want sequential consistency behavior when not using system |
| allocations or fine-grain SVM buffers with atomics support, use only |
| <strong>memory_order_seq_cst</strong> operations with the scope <strong>memory_scope_device</strong> |
| or <strong>memory_scope_all_svm_devices</strong>.</p> |
| </li> |
| <li> |
| <p>Ensure your program has no races.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>If these guidelines are followed in your OpenCL programs, you can skip the |
| detailed rules behind the relaxed memory models and go directly to |
| <a href="#opencl-framework">OpenCL Framework</a>.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_memory_model_overview_of_atomic_and_fence_operations">3.3.5. Memory Model: Overview of atomic and fence operations</h4> |
| <div class="paragraph"> |
| <p>The OpenCL 2.0 specification defines a number of <em>synchronization |
| operations</em> that are used to define memory order constraints in a program. |
| They play a special role in controlling how memory operations in one unit of |
| execution (such as work-items or, when using SVM a host thread) are made |
| visible to another. |
| There are two types of synchronization operations in OpenCL; <em>atomic |
| operations</em> and <em>fences</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Atomic operations are indivisible. |
| They either occur completely or not at all. |
| These operations are used to order memory operations between units of |
| execution and hence they are parameterized with the memory_order and |
| memory_scope parameters defined by the OpenCL memory consistency model. |
| The atomic operations for OpenCL kernel languages are similar to the |
| corresponding operations defined by the C11 standard.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The OpenCL 2.0 atomic operations apply to variables of an atomic type (a |
| subset of those in the C11 standard) including atomic versions of the int, |
| uint, long, ulong, float, double, half, intptr_t, uintptr_t, size_t, and |
| ptrdiff_t types. |
| However, support for some of these atomic types depends on support for the |
| corresponding regular types.</p> |
| </div> |
| <div class="paragraph"> |
| <p>An atomic operation on one or more memory locations is either an acquire |
| operation, a release operation, or both an acquire and release operation. |
| An atomic operation without an associated memory location is a fence and can |
| be either an acquire fence, a release fence, or both an acquire and release |
| fence. |
| In addition, there are relaxed atomic operations, which do not have |
| synchronization properties, and atomic read-modify-write operations, which |
| have special characteristics. |
| <a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 5, modified.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>The orders <strong>memory_order_acquire</strong> (used for reads), <strong>memory_order_release</strong> |
| (used for writes), and <strong>memory_order_acq_rel</strong> (used for read-modify-write |
| operations) are used for simple communication between units of execution |
| using shared variables. |
| Informally, executing a <strong>memory_order_release</strong> on an atomic object A makes |
| all previous side effects visible to any unit of execution that later |
| executes a <strong>memory_order_acquire</strong> on A. |
| The orders <strong>memory_order_acquire</strong>, <strong>memory_order_release</strong>, and |
| <strong>memory_order_acq_rel</strong> do not provide sequential consistency for race-free |
| programs because they will not ensure that atomic stores followed by atomic |
| loads become visible to other threads in that order.</p> |
| </div> |
| <div id="atomic-fence-orders" class="paragraph"> |
| <p>The fence operation is atomic_work_item_fence, which includes a memory_order |
| argument as well as the memory_scope and cl_mem_fence_flags arguments. |
| Depending on the memory_order argument, this operation:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>has no effects, if <strong>memory_order_relaxed</strong>;</p> |
| </li> |
| <li> |
| <p>is an acquire fence, if <strong>memory_order_acquire</strong>;</p> |
| </li> |
| <li> |
| <p>is a release fence, if <strong>memory_order_release</strong>;</p> |
| </li> |
| <li> |
| <p>is both an acquire fence and a release fence, if <strong>memory_order_acq_rel</strong>;</p> |
| </li> |
| <li> |
| <p>is a sequentially-consistent fence with both acquire and release |
| semantics, if <strong>memory_order_seq_cst</strong>.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>If specified, the cl_mem_fence_flags argument must be CLK_IMAGE_MEM_FENCE, |
| CLK_GLOBAL_MEM_FENCE, CLK_LOCAL_MEM_FENCE, or CLK_GLOBAL_MEM_FENCE | |
| CLK_LOCAL_MEM_FENCE.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The atomic_work_item_fence(CLK_IMAGE_MEM_FENCE) built-in function must be |
| used to make sure that sampler-less writes are visible to later reads by the |
| same work-item. |
| Without use of the atomic_work_item_fence function, write-read coherence on |
| image objects is not guaranteed: if a work-item reads from an image to which |
| it has previously written without an intervening atomic_work_item_fence, it |
| is not guaranteed that those previous writes are visible to the work-item.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The synchronization operations in OpenCL can be parameterized by a |
| memory_scope. |
| Memory scopes control the extent that an atomic operation or fence is |
| visible with respect to the memory model. |
| These memory scopes may be used when performing atomic operations and fences |
| on global memory and local memory. |
| When used on global memory visibility is bounded by the capabilities of that |
| memory. |
| When used on a fine-grained non-atomic SVM buffer, a coarse-grained SVM |
| buffer, or a non-SVM buffer, operations parameterized with |
| <strong>memory_scope_all_svm_devices</strong> will behave as if they were parameterized |
| with <strong>memory_scope_device</strong>. |
| When used on local memory, visibility is bounded by the work-group and, as a |
| result, memory_scope with wider visibility than <strong>memory_scope_work_group</strong> |
| will be reduced to <strong>memory_scope_work_group</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Two actions <strong>A</strong> and <strong>B</strong> are defined to have an inclusive scope if they have |
| the same scope <strong>P</strong> such that:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>P</strong> is <strong>memory_scope_sub_group</strong> and <strong>A</strong> and <strong>B</strong> are executed by |
| work-items within the same sub-group.</p> |
| </li> |
| <li> |
| <p><strong>P</strong> is <strong>memory_scope_work_group</strong> and <strong>A</strong> and <strong>B</strong> are executed by |
| work-items within the same work-group.</p> |
| </li> |
| <li> |
| <p><strong>P</strong> is <strong>memory_scope_device</strong> and <strong>A</strong> and <strong>B</strong> are executed by work-items |
| on the same device when <strong>A</strong> and <strong>B</strong> apply to an SVM allocation or <strong>A</strong> |
| and <strong>B</strong> are executed by work-items in the same kernel or one of its |
| children when <strong>A</strong> and <strong>B</strong> apply to a cl_mem buffer.</p> |
| </li> |
| <li> |
| <p><strong>P</strong> is <strong>memory_scope_all_svm_devices</strong> if <strong>A</strong> and <strong>B</strong> are executed by |
| host threads or by work-items on one or more devices that can share SVM |
| memory with each other and the host process.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="memory-ordering-rules">3.3.6. Memory Model: Memory Ordering Rules</h4> |
| <div class="paragraph"> |
| <p>Fundamentally, the issue in a memory model is to understand the orderings in |
| time of modifications to objects in memory. |
| Modifying an object or calling a function that modifies an object are side |
| effects, i.e. changes in the state of the execution environment. |
| Evaluation of an expression in general includes both value computations and |
| initiation of side effects. |
| Value computation for an lvalue expression includes determining the identity |
| of the designated object. |
| <a href="#iso-c11">[C11 standard, Section 5.1.2.3, paragraph 2, modified.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>We assume that the OpenCL kernel language and host programming languages |
| have a sequenced-before relation between the evaluations executed by a |
| single unit of execution. |
| This sequenced-before relation is an asymmetric, transitive, pair-wise |
| relation between those evaluations, which induces a partial order among |
| them. |
| Given any two evaluations <strong>A</strong> and <strong>B</strong>, if <strong>A</strong> is sequenced-before <strong>B</strong>, then |
| the execution of <strong>A</strong> shall precede the execution of <strong>B</strong>. |
| (Conversely, if <strong>A</strong> is sequenced-before <strong>B</strong>, then <strong>B</strong> is sequenced-after |
| <strong>A</strong>.) If <strong>A</strong> is not sequenced-before or sequenced-after <strong>B</strong>, then <strong>A</strong> and |
| <strong>B</strong> are unsequenced. |
| Evaluations <strong>A</strong> and <strong>B</strong> are indeterminately sequenced when <strong>A</strong> is either |
| sequenced-before or sequenced-after <strong>B</strong>, but it is unspecified which. |
| <a href="#iso-c11">[C11 standard, Section 5.1.2.3, paragraph 3, modified.]</a></p> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| Sequenced-before is a partial order of the operations executed by a |
| single unit of execution (e.g. a host thread or work-item). |
| It generally corresponds to the source program order of those operations, |
| and is partial because of the undefined argument evaluation order of OpenCLs |
| kernel C language. |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>In an OpenCL kernel language, the value of an object visible to a work-item |
| W at a particular point is the initial value of the object, a value stored |
| in the object by W, or a value stored in the object by another work-item or |
| host thread, according to the rules below. |
| Depending on details of the host programming language, the value of an |
| object visible to a host thread may also be the value stored in that object |
| by another work-item or host thread. |
| <a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 2, modified.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>Two expression evaluations conflict if one of them modifies a memory |
| location and the other one reads or modifies the same memory location. |
| <a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 4.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>All modifications to a particular atomic object <strong>M</strong> occur in some particular |
| total order, called the modification order of <strong>M</strong>. |
| If <strong>A</strong> and <strong>B</strong> are modifications of an atomic object <strong>M</strong>, and <strong>A</strong> |
| happens-before <strong>B</strong>, then <strong>A</strong> shall precede <strong>B</strong> in the modification order of |
| <strong>M</strong>, which is defined below. |
| Note that the modification order of an atomic object <strong>M</strong> is independent of |
| whether <strong>M</strong> is in local or global memory. |
| <a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 7, modified.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>A release sequence begins with a release operation <strong>A</strong> on an atomic object |
| <strong>M</strong> and is the maximal contiguous sub-sequence of side effects in the |
| modification order of <strong>M</strong>, where the first operation is <strong>A</strong> and every |
| subsequent operation either is performed by the same work-item or host |
| thread that performed the release or is an atomic read-modify-write |
| operation. |
| <a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 10, modified.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>OpenCLs local and global memories are disjoint. |
| Kernels may access both kinds of memory while host threads may only access |
| global memory. |
| Furthermore, the <em>flags</em> argument of OpenCLs work_group_barrier function |
| specifies which memory operations the function will make visible: these |
| memory operations can be, for example, just the ones to local memory, or the |
| ones to global memory, or both. |
| Since the visibility of memory operations can be specified for local memory |
| separately from global memory, we define two related but independent |
| relations, <em>global-synchronizes-with</em> and <em>local-synchronizes-with</em>. |
| Certain operations on global memory may global-synchronize-with other |
| operations performed by another work-item or host thread. |
| An example is a release atomic operation in one work- item that |
| global-synchronizes-with an acquire atomic operation in a second work-item. |
| Similarly, certain atomic operations on local objects in kernels can |
| local-synchronize- with other atomic operations on those local objects. |
| <a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 11, modified.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>We define two separate happens-before relations: global-happens-before and |
| local-happens-before.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A global memory action <strong>A</strong> global-happens-before a global memory action <strong>B</strong> |
| if</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>A</strong> is sequenced before <strong>B</strong>, or</p> |
| </li> |
| <li> |
| <p><strong>A</strong> global-synchronizes-with <strong>B</strong>, or</p> |
| </li> |
| <li> |
| <p>For some global memory action <strong>C</strong>, <strong>A</strong> global-happens-before <strong>C</strong> and <strong>C</strong> |
| global-happens-before <strong>B</strong>.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>A local memory action <strong>A</strong> local-happens-before a local memory action <strong>B</strong> if</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>A</strong> is sequenced before <strong>B</strong>, or</p> |
| </li> |
| <li> |
| <p><strong>A</strong> local-synchronizes-with <strong>B</strong>, or</p> |
| </li> |
| <li> |
| <p>For some local memory action <strong>C</strong>, <strong>A</strong> local-happens-before <strong>C</strong> and <strong>C</strong> |
| local-happens-before <strong>B</strong>.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>An OpenCL implementation shall ensure that no program execution demonstrates |
| a cycle in either the local-happens-before relation or the |
| global-happens-before relation.</p> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| The global- and local-happens-before relations are critical to |
| defining what values are read and when data races occur. |
| The global-happens-before relation, for example, defines what global memory |
| operations definitely happen before what other global memory operations. |
| If an operation <strong>A</strong> global-happens-before operation <strong>B</strong> then <strong>A</strong> must occur |
| before <strong>B</strong>; in particular, any write done by <strong>A</strong> will be visible to <strong>B</strong>. |
| The local-happens-before relation has similar properties for local memory. |
| Programmers can use the local- and global-happens-before relations to reason |
| about the order of program actions. |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>A visible side effect <strong>A</strong> on a global object <strong>M</strong> with respect to a value |
| computation <strong>B</strong> of <strong>M</strong> satisfies the conditions:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>A</strong> global-happens-before <strong>B</strong>, and</p> |
| </li> |
| <li> |
| <p>there is no other side effect <strong>X</strong> to <strong>M</strong> such that <strong>A</strong> |
| global-happens-before <strong>X</strong> and <strong>X</strong> global-happens-before <strong>B</strong>.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>We define visible side effects for local objects <strong>M</strong> similarly. |
| The value of a non-atomic scalar object <strong>M</strong>, as determined by evaluation |
| <strong>B</strong>, shall be the value stored by the visible side effect <strong>A</strong>. |
| <a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 19, modified.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>The execution of a program contains a data race if it contains two |
| conflicting actions <strong>A</strong> and <strong>B</strong> in different units of execution, and</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>(1) at least one of <strong>A</strong> or <strong>B</strong> is not atomic, or <strong>A</strong> and <strong>B</strong> do not have |
| inclusive memory scope, and</p> |
| </li> |
| <li> |
| <p>(2) the actions are global actions unordered by the |
| global-happens-before relation or are local actions unordered by the |
| local-happens-before relation.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Any such data race results in undefined behavior. |
| <a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 25, modified.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>We also define the visible sequence of side effects on local and global |
| atomic objects. |
| The remaining paragraphs of this subsection define this sequence for a |
| global atomic object <strong>M</strong>; the visible sequence of side effects for a local |
| atomic object is defined similarly by using the local-happens-before |
| relation.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The visible sequence of side effects on a global atomic object <strong>M</strong>, with |
| respect to a value computation <strong>B</strong> of <strong>M</strong>, is a maximal contiguous |
| sub-sequence of side effects in the modification order of <strong>M</strong>, where the |
| first side effect is visible with respect to <strong>B</strong>, and for every side effect, |
| it is not the case that <strong>B</strong> global-happens-before it. |
| The value of <strong>M</strong>, as determined by evaluation <strong>B</strong>, shall be the value stored |
| by some operation in the visible sequence of <strong>M</strong> with respect to <strong>B</strong>. |
| <a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 22, modified.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>If an operation <strong>A</strong> that modifies an atomic object <strong>M</strong> global-happens before |
| an operation <strong>B</strong> that modifies <strong>M</strong>, then <strong>A</strong> shall be earlier than <strong>B</strong> in |
| the modification order of <strong>M</strong>. |
| This requirement is known as write-write coherence.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If a value computation <strong>A</strong> of an atomic object <strong>M</strong> global-happens-before a |
| value computation <strong>B</strong> of <strong>M</strong>, and <strong>A</strong> takes its value from a side effect <strong>X</strong> |
| on <strong>M</strong>, then the value computed by <strong>B</strong> shall either equal the value stored |
| by <strong>X</strong>, or be the value stored by a side effect <strong>Y</strong> on <strong>M</strong>, where <strong>Y</strong> |
| follows <strong>X</strong> in the modification order of <strong>M</strong>. |
| This requirement is known as read-read coherence. |
| <a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 22, modified.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>If a value computation <strong>A</strong> of an atomic object <strong>M</strong> global-happens-before an |
| operation <strong>B</strong> on <strong>M</strong>, then <strong>A</strong> shall take its value from a side effect <strong>X</strong> |
| on <strong>M</strong>, where <strong>X</strong> precedes <strong>B</strong> in the modification order of <strong>M</strong>. |
| This requirement is known as read-write coherence.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If a side effect <strong>X</strong> on an atomic object <strong>M</strong> global-happens-before a value |
| computation <strong>B</strong> of <strong>M</strong>, then the evaluation <strong>B</strong> shall take its value from |
| <strong>X</strong> or from a side effect <strong>Y</strong> that follows <strong>X</strong> in the modification order of |
| <strong>M</strong>. |
| This requirement is known as write-read coherence.</p> |
| </div> |
| <div class="sect4"> |
| <h5 id="_memory_ordering_rules_atomic_operations">Memory Ordering Rules: Atomic Operations</h5> |
| <div class="paragraph"> |
| <p>This and following sections describe how different program actions in kernel |
| C code and the host program contribute to the local- and |
| global-happens-before relations. |
| This section discusses ordering rules for OpenCL 2.0 atomic operations.</p> |
| </div> |
| <div class="paragraph"> |
| <p><a href="#device-side-enqueue">Device-side enqueue</a> defines the enumerated type |
| memory_order.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>For <strong>memory_order_relaxed</strong>, no operation orders memory.</p> |
| </li> |
| <li> |
| <p>For <strong>memory_order_release</strong>, <strong>memory_order_acq_rel</strong>, and |
| <strong>memory_order_seq_cst</strong>, a store operation performs a release operation |
| on the affected memory location.</p> |
| </li> |
| <li> |
| <p>For <strong>memory_order_acquire</strong>, <strong>memory_order_acq_rel</strong>, and |
| <strong>memory_order_seq_cst</strong>, a load operation performs an acquire operation |
| on the affected memory location. |
| <a href="#iso-c11">[C11 standard, Section 7.17.3, paragraphs 2-4, modified.]</a></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Certain built-in functions synchronize with other built-in functions |
| performed by another unit of execution. |
| This is true for pairs of release and acquire operations under specific |
| circumstances. |
| An atomic operation <strong>A</strong> that performs a release operation on a global object |
| <strong>M</strong> global-synchronizes-with an atomic operation <strong>B</strong> that performs an |
| acquire operation on <strong>M</strong> and reads a value written by any side effect in the |
| release sequence headed by <strong>A</strong>. |
| A similar rule holds for atomic operations on objects in local memory: an |
| atomic operation <strong>A</strong> that performs a release operation on a local object <strong>M</strong> |
| local-synchronizes-with an atomic operation <strong>B</strong> that performs an acquire |
| operation on <strong>M</strong> and reads a value written by any side effect in the release |
| sequence headed by <strong>A</strong>. |
| <a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 11, modified.]</a></p> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| Atomic operations specifying <strong>memory_order_relaxed</strong> are relaxed only |
| with respect to memory ordering. |
| Implementations must still guarantee that any given atomic access to a |
| particular atomic object be indivisible with respect to all other atomic |
| accesses to that object. |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>There shall exist a single total order <strong>S</strong> for all <strong>memory_order_seq_cst</strong> |
| operations that is consistent with the modification orders for all affected |
| locations, as well as the appropriate global-happens-before and |
| local-happens-before orders for those locations, such that each |
| <strong>memory_order_seq</strong> operation <strong>B</strong> that loads a value from an atomic object |
| <strong>M</strong> in global or local memory observes one of the following values:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>the result of the last modification <strong>A</strong> of <strong>M</strong> that precedes <strong>B</strong> in <strong>S</strong>, |
| if it exists, or</p> |
| </li> |
| <li> |
| <p>if <strong>A</strong> exists, the result of some modification of <strong>M</strong> in the visible |
| sequence of side effects with respect to <strong>B</strong> that is not |
| <strong>memory_order_seq_cst</strong> and that does not happen before <strong>A</strong>, or</p> |
| </li> |
| <li> |
| <p>if <strong>A</strong> does not exist, the result of some modification of <strong>M</strong> in the |
| visible sequence of side effects with respect to <strong>B</strong> that is not |
| <strong>memory_order_seq_cst</strong>. |
| <a href="#iso-c11">[C11 standard, Section 7.17.3, paragraph 6, modified.]</a></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Let X and Y be two <strong>memory_order_seq_cst</strong> operations. |
| If X local-synchronizes-with or global-synchronizes-with Y then X both |
| local-synchronizes-with Y and global-synchronizes-with Y.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the total order <strong>S</strong> exists, the following rules hold:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>For an atomic operation <strong>B</strong> that reads the value of an atomic object |
| <strong>M</strong>, if there is a <strong>memory_order_seq_cst</strong> fence <strong>X</strong> sequenced-before |
| <strong>B</strong>, then <strong>B</strong> observes either the last <strong>memory_order_seq_cst</strong> |
| modification of <strong>M</strong> preceding <strong>X</strong> in the total order <strong>S</strong> or a later |
| modification of <strong>M</strong> in its modification order. |
| <a href="#iso-c11">[C11 standard, Section 7.17.3, paragraph 9.]</a></p> |
| </li> |
| <li> |
| <p>For atomic operations <strong>A</strong> and <strong>B</strong> on an atomic object <strong>M</strong>, where <strong>A</strong> |
| modifies <strong>M</strong> and <strong>B</strong> takes its value, if there is a |
| <strong>memory_order_seq_cst</strong> fence <strong>X</strong> such that <strong>A</strong> is sequenced-before <strong>X</strong> |
| and <strong>B</strong> follows <strong>X</strong> in <strong>S</strong>, then <strong>B</strong> observes either the effects of <strong>A</strong> |
| or a later modification of <strong>M</strong> in its modification order. |
| <a href="#iso-c11">[C11 standard, Section 7.17.3, paragraph 10.]</a></p> |
| </li> |
| <li> |
| <p>For atomic operations <strong>A</strong> and <strong>B</strong> on an atomic object <strong>M</strong>, where <strong>A</strong> |
| modifies <strong>M</strong> and <strong>B</strong> takes its value, if there are |
| <strong>memory_order_seq_cst</strong> fences <strong>X</strong> and <strong>Y</strong> such that <strong>A</strong> is |
| sequenced-before <strong>X</strong>, <strong>Y</strong> is sequenced-before <strong>B</strong>, and <strong>X</strong> precedes <strong>Y</strong> |
| in <strong>S</strong>, then <strong>B</strong> observes either the effects of <strong>A</strong> or a later |
| modification of <strong>M</strong> in its modification order. |
| <a href="#iso-c11">[C11 standard, Section 7.17.3, paragraph 11.]</a></p> |
| </li> |
| <li> |
| <p>For atomic operations <strong>A</strong> and <strong>B</strong> on an atomic object <strong>M</strong>, if there are |
| <strong>memory_order_seq_cst</strong> fences <strong>X</strong> and <strong>Y</strong> such that <strong>A</strong> is |
| sequenced-before <strong>X</strong>, <strong>Y</strong> is sequenced-before <strong>B</strong>, and <strong>X</strong> precedes <strong>Y</strong> |
| in <strong>S</strong>, then <strong>B</strong> occurs later than <strong>A</strong> in the modification order of <strong>M</strong>.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| <strong>memory_order_seq_cst</strong> ensures sequential consistency only for a |
| program that is (1) free of data races, and (2) exclusively uses |
| <strong>memory_order_seq_cst</strong> synchronization operations. |
| Any use of weaker ordering will invalidate this guarantee unless extreme |
| care is used. |
| In particular, <strong>memory_order_seq_cst</strong> fences ensure a total order only for |
| the fences themselves. |
| Fences cannot, in general, be used to restore sequential consistency for |
| atomic operations with weaker ordering specifications. |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>Atomic read-modify-write operations should always read the last value (in |
| the modification order) stored before the write associated with the |
| read-modify-write operation. |
| <a href="#iso-c11">[C11 standard, Section 7.17.3, paragraph 12.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p><span class="underline">Implementations should ensure that no "out-of-thin-air" values |
| are computed that circularly depend on their own computation.</span></p> |
| </div> |
| <div class="paragraph"> |
| <p>Note: Under the rules described above, and independent to the previously |
| footnoted C++ issue, it is known that <em>x == y == 42</em> is a valid final state |
| in the following problematic example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">global atomic_int x = ATOMIC_VAR_INIT(<span class="integer">0</span>); |
| local atomic_int y = ATOMIC_VAR_INIT(<span class="integer">0</span>); |
| |
| <span class="label">unit_of_execution_1:</span> |
| ... [execution not reading or writing x or y, leading up to:] |
| <span class="predefined-type">int</span> t = atomic_load_explicit(&y, memory_order_acquire); |
| atomic_store_explicit(&x, t, memory_order_release); |
| |
| <span class="label">unit_of_execution_2:</span> |
| ... [execution not reading or writing x or y, leading up to:] |
| <span class="predefined-type">int</span> t = atomic_load_explicit(&x, memory_order_acquire); |
| atomic_store_explicit(&y, t, memory_order_release);</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This is not useful behavior and implementations should not exploit this |
| phenomenon. |
| It should be expected that in the future this may be disallowed by |
| appropriate updates to the memory model description by the OpenCL committee.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Implementations should make atomic stores visible to atomic loads within a |
| reasonable amount of time. |
| <a href="#iso-c11">[C11 standard, Section 7.17.3, paragraph 16.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>As long as the following conditions are met, a host program sharing SVM |
| memory with a kernel executing on one or more OpenCL devices may use atomic |
| and synchronization operations to ensure that its assignments, and those of |
| the kernel, are visible to each other:</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p>Either fine-grained buffer or fine-grained system SVM must be used to |
| share memory. |
| While coarse-grained buffer SVM allocations may support atomic |
| operations, visibility on these allocations is not guaranteed except at |
| map and unmap operations.</p> |
| </li> |
| <li> |
| <p>The optional OpenCL 2.0 SVM atomic-controlled visibility specified by |
| provision of the CL_MEM_SVM_ATOMICS flag must be supported by the device |
| and the flag provided to the SVM buffer on allocation.</p> |
| </li> |
| <li> |
| <p>The host atomic and synchronization operations must be compatible with |
| those of an OpenCL kernel language. |
| This requires that the size and representation of the data types that |
| the host atomic operations act on be consistent with the OpenCL kernel |
| language atomic types.</p> |
| </li> |
| </ol> |
| </div> |
| <div class="paragraph"> |
| <p>If these conditions are met, the host operations will apply at |
| all_svm_devices scope.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="memory-ordering-fence">Memory Ordering Rules: Fence Operations</h5> |
| <div class="paragraph"> |
| <p>This section describes how the OpenCL 2.0 fence operations contribute to the |
| local- and global-happens-before relations.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Earlier, we introduced synchronization primitives called fences. |
| Fences can utilize the acquire memory_order, release memory_order, or both. |
| A fence with acquire semantics is called an acquire fence; a fence with |
| release semantics is called a release fence. The <a href="#atomic-fence-orders">overview of atomic and fence operations</a> section describes the memory orders |
| that result in acquire and release fences.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A global release fence <strong>A</strong> global-synchronizes-with a global acquire fence |
| <strong>B</strong> if there exist atomic operations <strong>X</strong> and <strong>Y</strong>, both operating on some |
| global atomic object <strong>M</strong>, such that <strong>A</strong> is sequenced-before <strong>X</strong>, <strong>X</strong> |
| modifies <strong>M</strong>, <strong>Y</strong> is sequenced-before <strong>B</strong>, <strong>Y</strong> reads the value written by |
| <strong>X</strong> or a value written by any side effect in the hypothetical release |
| sequence <strong>X</strong> would head if it were a release operation, and that the scopes |
| of <strong>A</strong>, <strong>B</strong> are inclusive. |
| <a href="#iso-c11">[C11 standard, Section 7.17.4, paragraph 2, modified.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>A global release fence <strong>A</strong> global-synchronizes-with an atomic operation <strong>B</strong> |
| that performs an acquire operation on a global atomic object <strong>M</strong> if there |
| exists an atomic operation <strong>X</strong> such that <strong>A</strong> is sequenced-before <strong>X</strong>, <strong>X</strong> |
| modifies <strong>M</strong>, <strong>B</strong> reads the value written by <strong>X</strong> or a value written by any |
| side effect in the hypothetical release sequence <strong>X</strong> would head if it were a |
| release operation, and the scopes of <strong>A</strong> and <strong>B</strong> are inclusive. |
| <a href="#iso-c11">[C11 standard, Section 7.17.4, paragraph 3, modified.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>An atomic operation <strong>A</strong> that is a release operation on a global atomic |
| object <strong>M</strong> global-synchronizes-with a global acquire fence <strong>B</strong> if there |
| exists some atomic operation <strong>X</strong> on <strong>M</strong> such that <strong>X</strong> is sequenced-before |
| <strong>B</strong> and reads the value written by <strong>A</strong> or a value written by any side effect |
| in the release sequence headed by <strong>A</strong>, and the scopes of <strong>A</strong> and <strong>B</strong> are |
| inclusive. |
| <a href="#iso-c11">[C11 standard, Section 7.17.4, paragraph 4, modified.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>A local release fence <strong>A</strong> local-synchronizes-with a local acquire fence <strong>B</strong> |
| if there exist atomic operations <strong>X</strong> and <strong>Y</strong>, both operating on some local |
| atomic object <strong>M</strong>, such that <strong>A</strong> is sequenced-before <strong>X</strong>, <strong>X</strong> modifies <strong>M</strong>, |
| <strong>Y</strong> is sequenced-before <strong>B</strong>, and <strong>Y</strong> reads the value written by <strong>X</strong> or a |
| value written by any side effect in the hypothetical release sequence <strong>X</strong> |
| would head if it were a</p> |
| </div> |
| <div class="paragraph"> |
| <p>release operation, and the scopes of <strong>A</strong> and <strong>B</strong> are inclusive. |
| <a href="#iso-c11">[C11 standard, Section 7.17.4, paragraph 2, modified.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>A local release fence <strong>A</strong> local-synchronizes-with an atomic operation <strong>B</strong> |
| that performs an acquire operation on a local atomic object <strong>M</strong> if there |
| exists an atomic operation <strong>X</strong> such that <strong>A</strong> is sequenced-before <strong>X</strong>, <strong>X</strong> |
| modifies <strong>M</strong>, and <strong>B</strong> reads the value written by <strong>X</strong> or a value written by |
| any side effect in the hypothetical release sequence <strong>X</strong> would head if it |
| were a release operation, and the scopes of <strong>A</strong> and <strong>B</strong> are inclusive. |
| <a href="#iso-c11">[C11 standard, Section 7.17.4, paragraph 3, modified.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>An atomic operation <strong>A</strong> that is a release operation on a local atomic object |
| <strong>M</strong> local-synchronizes-with a local acquire fence <strong>B</strong> if there exists some |
| atomic operation <strong>X</strong> on <strong>M</strong> such that <strong>X</strong> is sequenced-before <strong>B</strong> and reads |
| the value written by <strong>A</strong> or a value written by any side effect in the |
| release sequence headed by <strong>A</strong>, and the scopes of <strong>A</strong> and <strong>B</strong> are inclusive. |
| <a href="#iso-c11">[C11 standard, Section 7.17.4, paragraph 4, modified.]</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>Let <strong>X</strong> and <strong>Y</strong> be two work item fences that each have both the |
| CLK_GLOBAL_MEM_FENCE and CLK_LOCAL_MEM_FENCE flags set. |
| <strong>X</strong> global-synchronizes-with <strong>Y</strong> and <strong>X</strong> local synchronizes with <strong>Y</strong> if the |
| conditions required for <strong>X</strong> to global-synchronize with <strong>Y</strong> are met, the |
| conditions required for <strong>X</strong> to local-synchronize-with <strong>Y</strong> are met, or both |
| sets of conditions are met.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="_memory_ordering_rules_work_group_functions">Memory Ordering Rules: Work-group Functions</h5> |
| <div class="paragraph"> |
| <p>The OpenCL kernel execution model includes collective operations across the |
| work-items within a single work-group. |
| These are called work-group functions. |
| Besides the work-group barrier function, they include the scan, reduction |
| and pipe work-group functions described in the SPIR-V IL specifications. |
| We will first discuss the work-group barrier. |
| The other work-group functions are discussed afterwards.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The barrier function provides a mechanism for a kernel to synchronize the |
| work-items within a single work-group: informally, each work-item of the |
| work-group must execute the barrier before any are allowed to proceed. |
| It also orders memory operations to a specified combination of one or more |
| address spaces such as local memory or global memory, in a similar manner to |
| a fence.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To precisely specify the memory ordering semantics for barrier, we need to |
| distinguish between a dynamic and a static instance of the call to a |
| barrier. |
| A call to a barrier can appear in a loop, for example, and each execution of |
| the same static barrier call results in a new dynamic instance of the |
| barrier that will independently synchronize a work-groups work-items.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A work-item executing a dynamic instance of a barrier results in two |
| operations, both fences, that are called the entry and exit fences. |
| These fences obey all the rules for fences specified elsewhere in this |
| chapter as well as the following:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>The entry fence is a release fence with the same flags and scope as |
| requested for the barrier.</p> |
| </li> |
| <li> |
| <p>The exit fence is an acquire fence with the same flags and scope as |
| requested for the barrier.</p> |
| </li> |
| <li> |
| <p>For each work-item the entry fence is sequenced before the exit fence.</p> |
| </li> |
| <li> |
| <p>If the flags have CLK_GLOBAL_MEM_FENCE set then for each work-item the |
| entry fence global-synchronizes-with the exit fence of all other |
| work-items in the same work-group.</p> |
| </li> |
| <li> |
| <p>If the flags have CLK_LOCAL_MEM_FENCE set then for each work-item the |
| entry fence local-synchronizes-with the exit fence of all other |
| work-items in the same work-group.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The other work-group functions include such functions as work_group_all() |
| and work_group_broadcast() and are described in the kernel language and IL |
| specifications. |
| The use of these work-group functions implies sequenced-before relationships |
| between statements within the execution of a single work-item in order to |
| satisfy data dependencies. |
| For example, a work item that provides a value to a work-group function must |
| behave as if it generates that value before beginning execution of that |
| work-group function. |
| Furthermore, the programmer must ensure that all work items in a work group |
| must execute the same work-group function call site, or dynamic work-group |
| function instance.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="_memory_ordering_rules_sub_group_functions">Memory Ordering Rules: Sub-group Functions</h5> |
| <div class="paragraph"> |
| <p>The OpenCL kernel execution model includes collective operations across the |
| work-items within a single sub-group. |
| These are called sub-group functions. |
| Besides the sub-group-barrier function, they include the scan, reduction and |
| pipe sub-group functions described in the SPIR-V IL specification. |
| We will first discuss the sub-group barrier. |
| The other sub-group functions are discussed afterwards.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The barrier function provides a mechanism for a kernel to synchronize the |
| work-items within a single sub-group: informally, each work-item of the |
| sub-group must execute the barrier before any are allowed to proceed. |
| It also orders memory operations to a specified combination of one or more |
| address spaces such as local memory or global memory, in a similar manner to |
| a fence.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To precisely specify the memory ordering semantics for barrier, we need to |
| distinguish between a dynamic and a static instance of the call to a |
| barrier. |
| A call to a barrier can appear in a loop, for example, and each execution of |
| the same static barrier call results in a new dynamic instance of the |
| barrier that will independently synchronize a sub-groups work-items.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A work-item executing a dynamic instance of a barrier results in two |
| operations, both fences, that are called the entry and exit fences. |
| These fences obey all the rules for fences specified elsewhere in this |
| chapter as well as the following:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>The entry fence is a release fence with the same flags and scope as |
| requested for the barrier.</p> |
| </li> |
| <li> |
| <p>The exit fence is an acquire fence with the same flags and scope as |
| requested for the barrier.</p> |
| </li> |
| <li> |
| <p>For each work-item the entry fence is sequenced before the exit fence.</p> |
| </li> |
| <li> |
| <p>If the flags have CLK_GLOBAL_MEM_FENCE set then for each work-item the |
| entry fence global-synchronizes-with the exit fence of all other |
| work-items in the same sub-group.</p> |
| </li> |
| <li> |
| <p>If the flags have CLK_LOCAL_MEM_FENCE set then for each work-item the |
| entry fence local-synchronizes-with the exit fence of all other |
| work-items in the same sub-group.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The other sub-group functions include such functions as sub_group_all() and |
| sub_group_broadcast() and are described in OpenCL kernel languages |
| specifications. |
| The use of these sub-group functions implies sequenced-before relationships |
| between statements within the execution of a single work-item in order to |
| satisfy data dependencies. |
| For example, a work item that provides a value to a sub-group function must |
| behave as if it generates that value before beginning execution of that |
| sub-group function. |
| Furthermore, the programmer must ensure that all work items in a sub-group |
| must execute the same sub-group function call site, or dynamic sub-group |
| function instance.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="_memory_ordering_rules_host_side_and_device_side_commands">Memory Ordering Rules: Host-side and Device-side Commands</h5> |
| <div class="paragraph"> |
| <p>This section describes how the OpenCL API functions associated with |
| command-queues contribute to happens-before relations. |
| There are two types of command queues and associated API functions in OpenCL |
| 2.0; <em>host command-queues</em> and <em>device command-queues</em>. |
| The interaction of these command queues with the memory model are for the |
| most part equivalent. |
| In a few cases, the rules only applies to the host command-queue. |
| We will indicate these special cases by specifically denoting the host |
| command-queue in the memory ordering rule. |
| SVM memory consistency in such instances is implied only with respect to |
| synchronizing host commands.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Memory ordering rules in this section apply to all memory objects (buffers, |
| images and pipes) as well as to SVM allocations where no earlier, and more |
| fine-grained, rules apply.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In the remainder of this section, we assume that each command <strong>C</strong> enqueued |
| onto a command-queue has an associated event object <strong>E</strong> that signals its |
| execution status, regardless of whether <strong>E</strong> was returned to the unit of |
| execution that enqueued <strong>C</strong>. |
| We also distinguish between the API function call that enqueues a command |
| <strong>C</strong> and creates an event <strong>E</strong>, the execution of <strong>C</strong>, and the completion of |
| <strong>C</strong>(which marks the event <strong>E</strong> as complete).</p> |
| </div> |
| <div class="paragraph"> |
| <p>The ordering and synchronization rules for API commands are defined as |
| following:</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p>If an API function call <strong>X</strong> enqueues a command <strong>C</strong>, then <strong>X</strong> |
| global-synchronizes-with <strong>C</strong>. |
| For example, a host API function to enqueue a kernel |
| global-synchronizes-with the start of that kernel-instances execution, |
| so that memory updates sequenced-before the enqueue kernel function call |
| will global-happen-before any kernel reads or writes to those same |
| memory locations. |
| For a device-side enqueue, global memory updates sequenced before <strong>X</strong> |
| happens-before <strong>C</strong> reads or writes to those memory locations only in the |
| case of fine-grained SVM.</p> |
| </li> |
| <li> |
| <p>If <strong>E</strong> is an event upon which a command <strong>C</strong> waits, then <strong>E</strong> |
| global-synchronizes-with <strong>C</strong>. |
| In particular, if <strong>C</strong> waits on an event <strong>E</strong> that is tracking the |
| execution status of the command <strong>C1</strong>, then memory operations done by |
| <strong>C1</strong> will global-happen-before memory operations done by <strong>C</strong>. |
| As an example, assume we have an OpenCL program using coarse-grain SVM |
| sharing that enqueues a kernel to a host command-queue to manipulate the |
| contents of a region of a buffer that the host thread then accesses |
| after the kernel completes. |
| To do this, the host thread can call <strong>clEnqueueMapBuffer</strong> to enqueue a |
| blocking-mode map command to map that buffer region, specifying that the |
| map command must wait on an event signaling the kernels completion. |
| When <strong>clEnqueueMapBuffer</strong> returns, any memory operations performed by |
| the kernel to that buffer region will global- happen-before subsequent |
| memory operations made by the host thread.</p> |
| </li> |
| <li> |
| <p>If a command <strong>C</strong> has an event <strong>E</strong> that signals its completion, then <strong>C</strong> |
| global- synchronizes-with <strong>E</strong>.</p> |
| </li> |
| <li> |
| <p>For a command <strong>C</strong> enqueued to a host-side command queue, if <strong>C</strong> has an |
| event <strong>E</strong> that signals its completion, then <strong>E</strong> global-synchronizes-with |
| an API call <strong>X</strong> that waits on <strong>E</strong>. |
| For example, if a host thread or kernel-instance calls the |
| wait-for-events function on <strong>E</strong> (e.g. the <strong>clWaitForEvents</strong> function |
| called from a host thread), then <strong>E</strong> global-synchronizes-with that |
| wait-for-events function call.</p> |
| </li> |
| <li> |
| <p>If commands <strong>C</strong> and <strong>C1</strong> are enqueued in that sequence onto an in-order |
| command-queue, then the event (including the event implied between <strong>C</strong> |
| and <strong>C1</strong> due to the in-order queue) signaling <strong>C</strong>'s completion |
| global-synchronizes-with <strong>C1</strong>. |
| Note that in OpenCL 2.0, only a host command-queue can be configured as |
| an in-order queue.</p> |
| </li> |
| <li> |
| <p>If an API call enqueues a marker command <strong>C</strong> with an empty list of |
| events upon which <strong>C</strong> should wait, then the events of all commands |
| enqueued prior to <strong>C</strong> in the command-queue global-synchronize-with <strong>C</strong>.</p> |
| </li> |
| <li> |
| <p>If a host API call enqueues a command-queue barrier command <strong>C</strong> with an |
| empty list of events on which <strong>C</strong> should wait, then the events of all |
| commands enqueued prior to <strong>C</strong> in the command-queue |
| global-synchronize-with <strong>C</strong>. |
| In addition, the event signaling the completion of <strong>C</strong> |
| global-synchronizes-with all commands enqueued after <strong>C</strong> in the |
| command-queue.</p> |
| </li> |
| <li> |
| <p>If a host thread executes a <strong>clFinish</strong> call <strong>X</strong>, then the events of all |
| commands enqueued prior to <strong>X</strong> in the command-queue |
| global-synchronizes-with <strong>X</strong>.</p> |
| </li> |
| <li> |
| <p>The start of a kernel-instance <strong>K</strong> global-synchronizes-with all |
| operations in the work items of <strong>K</strong>. |
| Note that this includes the execution of any atomic operations by the |
| work items in a program using fine-grain SVM.</p> |
| </li> |
| <li> |
| <p>All operations of all work items of a kernel-instance <strong>K</strong> |
| global-synchronizes-with the event signaling the completion of <strong>K</strong>. |
| Note that this also includes the execution of any atomic operations by |
| the work items in a program using fine-grain SVM.</p> |
| </li> |
| <li> |
| <p>If a callback procedure <strong>P</strong> is registered on an event <strong>E</strong>, then <strong>E</strong> |
| global-synchronizes-with all operations of <strong>P</strong>. |
| Note that callback procedures are only defined for commands within host |
| command-queues.</p> |
| </li> |
| <li> |
| <p>If <strong>C</strong> is a command that waits for an event <strong>E</strong>'s completion, and API |
| function call <strong>X</strong> sets the status of a user event <strong>E</strong>'s status to |
| CL_COMPLETE (for example, from a host thread using a |
| <strong>clSetUserEventStatus</strong> function), then <strong>X</strong> global-synchronizes-with <strong>C</strong>.</p> |
| </li> |
| <li> |
| <p>If a device enqueues a command <strong>C</strong> with the |
| CLK_ENQUEUE_FLAGS_WAIT_KERNEL flag, then the end state of the parent |
| kernel instance global-synchronizes with <strong>C</strong>.</p> |
| </li> |
| <li> |
| <p>If a work-group enqueues a command <strong>C</strong> with the |
| CLK_ENQUEUE_FLAGS_WAIT_WORK_GROUP flag, then the end state of the |
| work-group global-synchronizes with <strong>C</strong>.</p> |
| </li> |
| </ol> |
| </div> |
| <div class="paragraph"> |
| <p>When using an out-of-order command queue, a wait on an event or a marker or |
| command-queue barrier command can be used to ensure the correct ordering of |
| dependent commands. |
| In those cases, the wait for the event or the marker or barrier command will |
| provide the necessary global-synchronizes-with relation.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In this situation:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>access to shared locations or disjoint locations in a single cl_mem |
| object when using atomic operations from different kernel instances |
| enqueued from the host such that one or more of the atomic operations is |
| a write is implementation-defined and correct behavior is not guaranteed |
| except at synchronization points.</p> |
| </li> |
| <li> |
| <p>access to shared locations or disjoint locations in a single cl_mem |
| object when using atomic operations from different kernel instances |
| consisting of a parent kernel and any number of child kernels enqueued |
| by that kernel is guaranteed under the memory ordering rules described |
| earlier in this section.</p> |
| </li> |
| <li> |
| <p>access to shared locations or disjoint locations in a single program |
| scope global variable, coarse-grained SVM allocation or fine-grained SVM |
| allocation when using atomic operations from different kernel instances |
| enqueued from the host to a single device is guaranteed under the memory |
| ordering rules described earlier in this section.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>If fine-grain SVM is used but without support for the OpenCL 2.0 atomic |
| operations, then the host and devices can concurrently read the same memory |
| locations and can concurrently update non-overlapping memory regions, but |
| attempts to update the same memory locations are undefined. |
| Memory consistency is guaranteed at the OpenCL synchronization points |
| without the need for calls to <strong>clEnqueueMapBuffer</strong> and |
| <strong>clEnqueueUnmapMemObject</strong>. |
| For fine-grained SVM buffers it is guaranteed that at synchronization points |
| only values written by the kernel will be updated. |
| No writes to fine-grained SVM buffers can be introduced that were not in the |
| original program.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In the remainder of this section, we discuss a few points regarding the |
| ordering rules for commands with a host command queue.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The OpenCL 1.2 standard describes a synchronization point as a |
| kernel-instance or host program location where the contents of memory |
| visible to different work-items or command-queue commands are the same. |
| It also says that waiting on an event and a command-queue barrier are |
| synchronization points between commands in command- queues. |
| Four of the rules listed above (2, 4, 7, and 8) cover these OpenCL |
| synchronization points.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A map operation (<strong>clEnqueueMapBuffer</strong> or <strong>clEnqueueMapImage</strong>) performed on a |
| non-SVM buffer or a coarse-grained SVM buffer is allowed to overwrite the |
| entire target region with the latest runtime view of the data as seen by the |
| command with which the map operation synchronizes, whether the values were |
| written by the executing kernels or not. |
| Any values that were changed within this region by another kernel or host |
| thread while the kernel synchronizing with the map operation was executing |
| may be overwritten by the map operation.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Access to non-SVM cl_mem buffers and coarse-grained SVM allocations is |
| ordered at synchronization points between host commands. |
| In the presence of an out-of-order command queue or a set of command queues |
| mapped to the same device, multiple kernel instances may execute |
| concurrently on the same device.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="opencl-framework">3.4. The OpenCL Framework</h3> |
| <div class="paragraph"> |
| <p>The OpenCL framework allows applications to use a host and one or more |
| OpenCL devices as a single heterogeneous parallel computer system. |
| The framework contains the following components:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>OpenCL Platform layer</strong>: The platform layer allows the host program to |
| discover OpenCL devices and their capabilities and to create contexts.</p> |
| </li> |
| <li> |
| <p><strong>OpenCL Runtime</strong>: The runtime allows the host program to manipulate |
| contexts once they have been created.</p> |
| </li> |
| <li> |
| <p><strong>OpenCL Compiler</strong>: The OpenCL compiler creates program executables that |
| contain OpenCL kernels. |
| SPIR-V intermediate language, OpenCL C, OpenCL C++, and OpenCL C |
| language versions from earlier OpenCL specifications are supported by |
| the compiler. |
| Other input languages may be supported by some implementations.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="sect3"> |
| <h4 id="_opencl_framework_mixed_version_support">3.4.1. OpenCL Framework: Mixed Version Support</h4> |
| <div class="paragraph"> |
| <p>OpenCL supports devices with different capabilities under a single platform. |
| This includes devices which conform to different versions of the OpenCL |
| specification. |
| There are three version identifiers to consider for an OpenCL system: the |
| platform version, the version of a device, and the version(s) of the kernel |
| language or IL supported on a device.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The platform version indicates the version of the OpenCL runtime that is |
| supported. |
| This includes all of the APIs that the host can use to interact with |
| resources exposed by the OpenCL runtime; including contexts, memory objects, |
| devices, and command queues.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The device version is an indication of the device’s capabilities separate |
| from the runtime and compiler as represented by the device info returned by |
| <strong>clGetDeviceInfo</strong>. |
| Examples of attributes associated with the device version are resource |
| limits (e.g., minimum size of local memory per compute unit) and extended |
| functionality (e.g., list of supported KHR extensions). |
| The version returned corresponds to the highest version of the OpenCL |
| specification for which the device is conformant, but is not higher than the |
| platform version.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The language version for a device represents the OpenCL programming language |
| features a developer can assume are supported on a given device. |
| The version reported is the highest version of the language supported.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Backwards compatibility is an important goal for the OpenCL standard. |
| Backwards compatibility is expected such that a device will consume earlier |
| versions of the SPIR-V and OpenCL C programming languages with the following |
| minimum requirements:</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p>An OpenCL 1.x device must support at least one 1.x version of the OpenCL |
| C programming language.</p> |
| </li> |
| <li> |
| <p>An OpenCL 2.0 device must support all the requirements of an OpenCL 1.x |
| device in addition to the OpenCL C 2.0 programming language. |
| If multiple language versions are supported, the compiler defaults to |
| using the highest OpenCL 1.x language version supported for the device |
| (typically OpenCL 1.2). |
| To utilize the OpenCL 2.0 Kernel programming language, a programmer must |
| specifically set the appropriate compiler flag (-cl-std=CL2.0). |
| The language version must not be higher than the platform version, but |
| may exceed the <a href="#opencl-c-version">device version</a>.</p> |
| </li> |
| <li> |
| <p>An OpenCL 2.1 device must support all the requirements of an OpenCL 2.0 |
| device in addition to the SPIR-V intermediate language at version 1.0 or |
| above. |
| Intermediate language versioning is encoded as part of the binary object |
| and no flags are required to be passed to the compiler.</p> |
| </li> |
| <li> |
| <p>An OpenCL 2.2 device must support all the requirements of an OpenCL 2.0 |
| device in addition to the SPIR-V intermediate language at version 1.2 or |
| above. |
| Intermediate language is encoded as a part of the binary object and no |
| flags are required to be passed to the compiler.</p> |
| </li> |
| </ol> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="opencl-platform-layer">4. The OpenCL Platform Layer</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>This section describes the OpenCL platform layer which implements |
| platform-specific features that allow applications to query OpenCL devices, |
| device configuration information, and to create OpenCL contexts using one or |
| more devices.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="_querying_platform_info">4.1. Querying Platform Info</h3> |
| <div class="paragraph"> |
| <p>The list of platforms available can be obtained using the following |
| function.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetPlatformIDs(cl_uint num_entries, |
| cl_platform_id *platforms, |
| cl_uint *num_platforms)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><em>num_entries</em> is the number of cl_platform_id entries that can be added to |
| <em>platforms</em>. |
| If <em>platforms</em> is not <code>NULL</code>, the <em>num_entries</em> must be greater than zero.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>platforms</em> returns a list of OpenCL platforms found. |
| The cl_platform_id_ values returned in <em>platforms</em> can be used to identify a |
| specific OpenCL platform. |
| If <em>platforms</em> argument is <code>NULL</code>, this argument is ignored. |
| The number of OpenCL platforms returned is the minimum of the value |
| specified by <em>num_entries</em> or the number of OpenCL platforms available.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>num_platforms</em> returns the number of OpenCL platforms available. |
| If <em>num_platforms</em> is <code>NULL</code>, this argument is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clGetPlatformIDs</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_VALUE if <em>num_entries</em> is equal to zero and <em>platforms</em> is |
| not <code>NULL</code> or if both <em>num_platforms</em> and <em>platforms</em> are <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetPlatformInfo(cl_platform_id platform, |
| cl_platform_info param_name, |
| size_t param_value_size, |
| <span class="directive">void</span> *param_value, |
| size_t *param_value_size_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>gets specific information about the OpenCL platform. |
| The information that can be queried using <strong>clGetPlatformInfo</strong> is specified |
| in the <a href="#platform-queries-table">Platform Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>platform</em> refers to the platform ID returned by <strong>clGetPlatformIDs</strong> or can |
| be <code>NULL</code>. |
| If <em>platform</em> is <code>NULL</code>, the behavior is implementation-defined.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_name</em> is an enumeration constant that identifies the platform |
| information being queried. |
| It can be one of the following values as specified in the |
| <a href="#platform-queries-table">Platform Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value</em> is a pointer to memory location where appropriate values for a |
| given <em>param_name</em>, as specified in the <a href="#platform-queries-table">Platform |
| Queries</a> table, will be returned. |
| If <em>param_value</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size</em> specifies the size in bytes of memory pointed to by |
| <em>param_value</em>. |
| This size in bytes must be ≥ size of return type specified in the |
| <a href="#platform-queries-table">Platform Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size_ret</em> returns the actual size in bytes of data being |
| queried by <em>param_name</em>. |
| If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <table id="platform-queries-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 3. OpenCL Platform Queries</caption> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 10%;"> |
| <col style="width: 40%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_platform_info</strong></th> |
| <th class="tableblock halign-left valign-top">Return Type</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PLATFORM_PROFILE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]<sup>1</sup></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">OpenCL profile string. |
| Returns the profile name supported by the implementation. |
| The profile name returned can be one of the following strings:</p> |
| <p class="tableblock"> FULL_PROFILE - if the implementation supports the OpenCL |
| specification (functionality defined as part of the core |
| specification and does not require any extensions to be supported).</p> |
| <p class="tableblock"> EMBEDDED_PROFILE - if the implementation supports the OpenCL |
| embedded profile. |
| The embedded profile is defined to be a subset for each version of |
| OpenCL. |
| The embedded profile for OpenCL 2.2 is described in |
| <a href="#opencl-embedded-profile">OpenCL Embedded Profile</a>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PLATFORM_VERSION</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">OpenCL version string. |
| Returns the OpenCL version supported by the implementation. |
| This version string has the following format:</p> |
| <p class="tableblock"> <em>OpenCL<space><major_version.minor_version><space><platform-specific |
| information></em></p> |
| <p class="tableblock"> The <em>major_version.minor_version</em> value returned will be 2.2.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PLATFORM_NAME</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Platform name string.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PLATFORM_VENDOR</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Platform vendor string.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PLATFORM_EXTENSIONS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns a space separated list of extension names (the extension |
| names themselves do not contain any spaces) supported by the |
| platform. |
| Each extension that is supported by all devices associated with this |
| platform must be reported here.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PLATFORM_HOST_TIMER_RESOLUTION</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the resolution of the host timer in nanoseconds as used by |
| <strong>clGetDeviceAndHostTimer</strong>.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p><strong>clGetPlatformInfo</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors<sup>2</sup>.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_PLATFORM if <em>platform</em> is not a valid platform.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is not one of the supported values or |
| if size in bytes specified by <em>param_value_size</em> is < size of return |
| type as specified in the <a href="#platform-queries-table">OpenCL Platform |
| Queries</a> table, and <em>param_value</em> is not a <code>NULL</code> value.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">1</dt> |
| <dd> |
| <p>A null terminated string is returned by OpenCL query function calls if |
| the return type of the information being queried is a char[].</p> |
| </dd> |
| <dt class="hdlist1">2</dt> |
| <dd> |
| <p>The OpenCL specification does not describe the order of precedence for |
| error codes returned by API calls.</p> |
| </dd> |
| </dl> |
| </div> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="platform-querying-devices">4.2. Querying Devices</h3> |
| <div class="paragraph"> |
| <p>The list of devices available on a platform can be obtained using the |
| following function<sup>3</sup>.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetDeviceIDs(cl_platform_id platform, |
| cl_device_type device_type, |
| cl_uint num_entries, |
| cl_device_id * devices, |
| cl_uint *num_devices)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><em>platform</em> refers to the platform ID returned by <strong>clGetPlatformIDs</strong> or can |
| be <code>NULL</code>. |
| If <em>platform</em> is <code>NULL</code>, the behavior is implementation-defined.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>device_type</em> is a bitfield that identifies the type of OpenCL device. |
| The <em>device_type</em> can be used to query specific OpenCL devices or all OpenCL |
| devices available. |
| The valid values for <em>device_type</em> are specified in the |
| <a href="#device-categories-table">Device Categories</a> table.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">3</dt> |
| <dd> |
| <p><strong>clGetDeviceIDs</strong> may return all or a subset of the actual physical |
| devices present in the platform and that match <em>device_type</em>.</p> |
| </dd> |
| </dl> |
| </div> |
| <table id="device-categories-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 4. List of OpenCL Device Categories</caption> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_device_type</strong></th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_TYPE_CPU</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">An OpenCL device that is the host processor. |
| The host processor runs the OpenCL implementations and is a single or |
| multi-core CPU.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_TYPE_GPU</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">An OpenCL device that is a GPU. |
| By this we mean that the device can also be used to accelerate a 3D API |
| such as OpenGL or DirectX.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_TYPE_ACCELERATOR</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Dedicated OpenCL accelerators (for example the IBM CELL Blade). |
| These devices communicate with the host processor using a peripheral |
| interconnect such as PCIe.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_TYPE_CUSTOM</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Dedicated accelerators that do not support programs written in an OpenCL |
| kernel language,</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_TYPE_DEFAULT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The default OpenCL device in the system. |
| The default device cannot be a <strong>CL_DEVICE_TYPE_CUSTOM</strong> device.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_TYPE_ALL</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">All OpenCL devices available in the system except |
| <strong>CL_DEVICE_TYPE_CUSTOM</strong> devices..</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p><em>num_entries</em> is the number of cl_device_id entries that can be added to |
| <em>devices</em>. |
| If <em>devices</em> is not <code>NULL</code>, the <em>num_entries</em> must be greater than zero.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>devices</em> returns a list of OpenCL devices found. |
| The cl_device_id values returned in <em>devices</em> can be used to identify a |
| specific OpenCL device. |
| If <em>devices</em> argument is <code>NULL</code>, this argument is ignored. |
| The number of OpenCL devices returned is the minimum of the value specified |
| by <em>num_entries</em> or the number of OpenCL devices whose type matches |
| <em>device_type</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>num_devices</em> returns the number of OpenCL devices available that match |
| <em>device_type</em>. |
| If <em>num_devices</em> is <code>NULL</code>, this argument is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clGetDeviceIDs</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_PLATFORM if <em>platform</em> is not a valid platform.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_DEVICE_TYPE if <em>device_type</em> is not a valid value.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>num_entries</em> is equal to zero and <em>devices</em> is not |
| <code>NULL</code> or if both <em>num_devices</em> and <em>devices</em> are <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_DEVICE_NOT_FOUND if no OpenCL devices that matched <em>device_type</em> were |
| found.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The application can query specific capabilities of the OpenCL device(s) |
| returned by <strong>clGetDeviceIDs</strong>. |
| This can be used by the application to determine which device(s) to use.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetDeviceInfo(cl_device_id device, |
| cl_device_info param_name, |
| size_t param_value_size, |
| <span class="directive">void</span> *param_value, |
| size_t *param_value_size_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>gets specific information about an OpenCL device.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>device</em> may be a device returned by <strong>clGetDeviceIDs</strong> or a sub-device |
| created by <strong>clCreateSubDevices</strong>. |
| If <em>device</em> is a sub-device, the specific information for the sub-device |
| will be returned. |
| The information that can be queried using <strong>clGetDeviceInfo</strong> is specified in |
| the <a href="#device-queries-table">Device Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_name</em> is an enumeration constant that identifies the device |
| information being queried. |
| It can be one of the following values as specified in the |
| <a href="#device-queries-table">Device Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value</em> is a pointer to memory location where appropriate values for a |
| given <em>param_name</em>, as specified in the <a href="#device-queries-table">Device |
| Queries</a> table, will be returned. |
| If <em>param_value</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size</em> specifies the size in bytes of memory pointed to by |
| <em>param_value</em>. |
| This size in bytes must be ≥ size of return type specified in the |
| <a href="#device-queries-table">Device Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size_ret</em> returns the actual size in bytes of data being |
| queried by <em>param_name</em>. |
| If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <table id="device-queries-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 5. OpenCL Device Queries</caption> |
| <colgroup> |
| <col style="width: 30%;"> |
| <col style="width: 20%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_device_info</strong></th> |
| <th class="tableblock halign-left valign-top">Return Type</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_TYPE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_type</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The OpenCL device type. |
| Currently supported values are:</p> |
| <p class="tableblock"> CL_DEVICE_TYPE_CPU, CL_DEVICE_TYPE_GPU, CL_DEVICE_TYPE_ACCELERATOR, |
| CL_DEVICE_TYPE_DEFAULT, a combination of the above types or |
| CL_DEVICE_TYPE_CUSTOM.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_VENDOR_ID</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">A unique device vendor identifier. |
| An example of a unique device identifier could be the PCIe ID.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_COMPUTE_UNITS</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The number of parallel compute units on the OpenCL device. |
| A work-group executes on a single compute unit. |
| The minimum value is 1.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum dimensions that specify the global and local work-item IDs |
| used by the data parallel execution model. (Refer to |
| <strong>clEnqueueNDRangeKernel</strong>). |
| The minimum value is 3 for devices that are not of type |
| CL_DEVICE_TYPE_CUSTOM.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_WORK_ITEM_SIZES</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t []</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum number of work-items that can be specified in each dimension |
| of the work-group to <strong>clEnqueueNDRangeKernel</strong>.</p> |
| <p class="tableblock"> Returns <em>n</em> size_t entries, where <em>n</em> is the value returned by the |
| query for CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS.</p> |
| <p class="tableblock"> The minimum value is (1, 1, 1) for devices that are not of type |
| CL_DEVICE_TYPE_CUSTOM.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_WORK_GROUP_SIZE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum number of work-items in a work-group that a device is |
| capable of executing on a single compute unit, for any given |
| kernel-instance running on the device. (Refer also to |
| <strong>clEnqueueNDRangeKernel</strong> and CL_KERNEL_WORK_GROUP_SIZE ). |
| The minimum value is 1. |
| The returned value is an upper limit and will not necessarily |
| maximize performance. |
| This maximum may be larger than supported by a specific kernel |
| (refer to the CL_KERNEL_WORK_GROUP_SIZE query of <strong>clGetKernelWorkGroupInfo</strong>).</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR <br> |
| CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT <br> |
| CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT <br> |
| CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG <br> |
| CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT <br> |
| CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE<br> |
| CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Preferred native vector width size for built-in scalar types that |
| can be put into vectors. |
| The vector width is defined as the number of scalar elements that |
| can be stored in the vector.</p> |
| <p class="tableblock"> If double precision is not supported, |
| CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE must return 0.</p> |
| <p class="tableblock"> If the <strong>cl_khr_fp16</strong> extension is not supported, |
| CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF must return 0.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR <br> |
| CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT <br> |
| CL_DEVICE_NATIVE_VECTOR_WIDTH_INT <br> |
| CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG <br> |
| CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT <br> |
| CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE<br> |
| CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the native ISA vector width. |
| The vector width is defined as the number of scalar elements that |
| can be stored in the vector.</p> |
| <p class="tableblock"> If double precision is not supported, |
| CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE must return 0.</p> |
| <p class="tableblock"> If the <strong>cl_khr_fp16</strong> extension is not supported, |
| CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF must return 0.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_CLOCK_FREQUENCY</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Clock frequency of the device in MHz. |
| The meaning of this value is implementation-defined. |
| For devices with multiple clock domains, the clock frequency for any |
| of the clock domains may be returned. |
| For devices that dynamically change frequency for power or thermal |
| reasons, the returned clock frequency may be any valid frequency.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_ADDRESS_BITS</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The default compute device address space size of the global address |
| space specified as an unsigned integer value in bits. |
| Currently supported values are 32 or 64 bits.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_MEM_ALLOC_SIZE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max size of memory object allocation in bytes. |
| The minimum value is max(min(1024 × 1024 × 1024, 1/4<sup>th</sup> |
| of CL_DEVICE_GLOBAL_MEM_SIZE), 32 × 1024 × 1024) for |
| devices that are not of type CL_DEVICE_TYPE_CUSTOM.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE_SUPPORT</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_TRUE if images are supported by the OpenCL device and CL_FALSE |
| otherwise.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_READ_IMAGE_ARGS<sup>4</sup></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max number of image objects arguments of a kernel declared with the |
| read_only qualifier. |
| The minimum value is 128 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_WRITE_IMAGE_ARGS</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max number of image objects arguments of a kernel declared with the |
| write_only qualifier. |
| The minimum value is 64 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS<sup>5</sup></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max number of image objects arguments of a kernel declared with the |
| write_only or read_write qualifier. |
| The minimum value is 64 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IL_VERSION</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The intermediate languages that can be supported by |
| <strong>clCreateProgramWithIL</strong> for this device. |
| Returns a space-separated list of IL version strings of the form |
| <IL_Prefix>_<Major_Version>.<Minor_Version>. |
| For OpenCL 2.2, SPIR-V is a required IL prefix.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE2D_MAX_WIDTH</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max width of 2D image or 1D image not created from a buffer object |
| in pixels.</p> |
| <p class="tableblock"> The minimum value is 16384 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE2D_MAX_HEIGHT</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max height of 2D image in pixels.</p> |
| <p class="tableblock"> The minimum value is 16384 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE3D_MAX_WIDTH</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max width of 3D image in pixels.</p> |
| <p class="tableblock"> The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE3D_MAX_HEIGHT</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max height of 3D image in pixels.</p> |
| <p class="tableblock"> The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE3D_MAX_DEPTH</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max depth of 3D image in pixels.</p> |
| <p class="tableblock"> The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE_MAX_BUFFER_SIZE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max number of pixels for a 1D image created from a buffer object.</p> |
| <p class="tableblock"> The minimum value is 65536 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE_MAX_ARRAY_SIZE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max number of images in a 1D or 2D image array.</p> |
| <p class="tableblock"> The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_SAMPLERS</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum number of samplers that can be used in a kernel.</p> |
| <p class="tableblock"> The minimum value is 16 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE_PITCH_ALIGNMENT</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The row pitch alignment size in pixels for 2D images created from a |
| buffer. |
| The value returned must be a power of 2.</p> |
| <p class="tableblock"> If the device does not support images, this value must be 0.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This query should be used when a 2D image is created from a buffer |
| which was created using CL_MEM_USE_HOST_PTR. |
| The value returned must be a power of 2.</p> |
| <p class="tableblock"> This query specifies the minimum alignment in pixels of the host_ptr |
| specified to <strong>clCreateBuffer</strong>.</p> |
| <p class="tableblock"> If the device does not support images, this value must be 0.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_PIPE_ARGS</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The maximum number of pipe objects that can be passed as arguments |
| to a kernel. |
| The minimum value is 16.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The maximum number of reservations that can be active for a pipe per |
| work-item in a kernel. |
| A work-group reservation is counted as one reservation per |
| work-item. |
| The minimum value is 1.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PIPE_MAX_PACKET_SIZE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The maximum size of pipe packet in bytes. |
| The minimum value is 1024 bytes.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_PARAMETER_SIZE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max size in bytes of all arguments that can be passed to a kernel.</p> |
| <p class="tableblock"> The minimum value is 1024 for devices that are not of type |
| CL_DEVICE_TYPE_CUSTOM. |
| For this minimum value, only a maximum of 128 arguments can be |
| passed to a kernel</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MEM_BASE_ADDR_ALIGN</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Alignment requirement (in bits) for sub-buffer offsets. |
| The minimum value is the size (in bits) of the largest OpenCL |
| built-in data type supported by the device (long16 in FULL profile, |
| long16 or int16 in EMBEDDED profile) for devices that are not of |
| type CL_DEVICE_TYPE_CUSTOM.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_SINGLE_FP_CONFIG<sup>6</sup></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_fp_config</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Describes single precision floating-point capability of the device. |
| This is a bit-field that describes one or more of the following |
| values:</p> |
| <p class="tableblock"> CL_FP_DENORM - denorms are supported</p> |
| <p class="tableblock"> CL_FP_INF_NAN - INF and quiet NaNs are supported.</p> |
| <p class="tableblock"> CL_FP_ROUND_TO_NEAREST-- round to nearest even rounding mode |
| supported</p> |
| <p class="tableblock"> CL_FP_ROUND_TO_ZERO - round to zero rounding mode supported</p> |
| <p class="tableblock"> CL_FP_ROUND_TO_INF - round to positive and negative infinity |
| rounding modes supported</p> |
| <p class="tableblock"> CL_FP_FMA - IEEE754-2008 fused multiply-add is supported.</p> |
| <p class="tableblock"> CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT - divide and sqrt are correctly |
| rounded as defined by the IEEE754 specification.</p> |
| <p class="tableblock"> CL_FP_SOFT_FLOAT - Basic floating-point operations (such as |
| addition, subtraction, multiplication) are implemented in software.</p> |
| <p class="tableblock"> For the full profile, the mandated minimum floating-point capability |
| for devices that are not of type CL_DEVICE_TYPE_CUSTOM is: |
| CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN.</p> |
| <p class="tableblock"> For the embedded profile, see section 10.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_DOUBLE_FP_CONFIG<sup>7</sup></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_fp_config</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Describes double precision floating-point capability of the OpenCL |
| device. |
| This is a bit-field that describes one or more of the following |
| values:</p> |
| <p class="tableblock"> CL_FP_DENORM - denorms are supported</p> |
| <p class="tableblock"> CL_FP_INF_NAN - INF and NaNs are supported.</p> |
| <p class="tableblock"> CL_FP_ROUND_TO_NEAREST - round to nearest even rounding mode |
| supported.</p> |
| <p class="tableblock"> CL_FP_ROUND_TO_ZERO - round to zero rounding mode supported.</p> |
| <p class="tableblock"> CL_FP_ROUND_TO_INF - round to positive and negative infinity |
| rounding modes supported.</p> |
| <p class="tableblock"> CL_FP_FMA - IEEE754-2008 fused multiply-add is supported.</p> |
| <p class="tableblock"> CL_FP_SOFT_FLOAT - Basic floating-point operations (such as |
| addition, subtraction, multiplication) are implemented in software.</p> |
| <p class="tableblock"> Double precision is an optional feature so the mandated minimum |
| double precision floating-point capability is 0.</p> |
| <p class="tableblock"> If double precision is supported by the device, then the minimum |
| double precision floating-point capability must be:<br> |
| CL_FP_FMA |<br> |
| CL_FP_ROUND_TO_NEAREST |<br> |
| CL_FP_INF_NAN |<br> |
| CL_FP_DENORM.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_GLOBAL_MEM_CACHE_TYPE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_mem_cache_type</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Type of global memory cache supported. |
| Valid values are: CL_NONE, CL_READ_ONLY_CACHE and |
| CL_READ_WRITE_CACHE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Size of global memory cache line in bytes.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_GLOBAL_MEM_CACHE_SIZE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Size of global memory cache in bytes.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_GLOBAL_MEM_SIZE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Size of global device memory in bytes.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max size in bytes of a constant buffer allocation. |
| The minimum value is 64 KB for devices that are not of type |
| CL_DEVICE_TYPE_CUSTOM.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_CONSTANT_ARGS</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max number of arguments declared with the <code>__constant</code> qualifier |
| in a kernel. |
| The minimum value is 8 for devices that are not of type |
| CL_DEVICE_TYPE_CUSTOM.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The maximum number of bytes of storage that may be allocated for any |
| single variable in program scope or inside a function in an OpenCL |
| kernel language declared in the global address space.</p> |
| <p class="tableblock"> The minimum value is 64 KB.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum preferred total size, in bytes, of all program variables in |
| the global address space. |
| This is a performance hint. |
| An implementation may place such variables in storage with optimized |
| device access. |
| This query returns the capacity of such storage. |
| The minimum value is 0.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_LOCAL_MEM_TYPE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_local_mem_type</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Type of local memory supported. |
| This can be set to CL_LOCAL implying dedicated local memory storage |
| such as SRAM , or CL_GLOBAL.</p> |
| <p class="tableblock"> For custom devices, CL_NONE can also be returned indicating no local |
| memory support.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_LOCAL_MEM_SIZE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Size of local memory region in bytes. |
| The minimum value is 32 KB for devices that are not of type |
| CL_DEVICE_TYPE_CUSTOM.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_ERROR_CORRECTION_SUPPORT</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_TRUE if the device implements error correction for all |
| accesses to compute device memory (global and constant). |
| Is CL_FALSE if the device does not implement such error correction.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PROFILING_TIMER_RESOLUTION</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Describes the resolution of device timer. |
| This is measured in nanoseconds. |
| Refer to <a href="#profiling-operations">Profiling Operations</a> for details.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_ENDIAN_LITTLE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_TRUE if the OpenCL device is a little endian device and |
| CL_FALSE otherwise</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_AVAILABLE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_TRUE if the device is available and CL_FALSE otherwise. |
| A device is considered to be available if the device can be expected |
| to successfully execute commands enqueued to the device.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_COMPILER_AVAILABLE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_FALSE if the implementation does not have a compiler available |
| to compile the program source.</p> |
| <p class="tableblock"> Is CL_TRUE if the compiler is available. |
| This can be CL_FALSE for the embedded platform profile only.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_LINKER_AVAILABLE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_FALSE if the implementation does not have a linker available. |
| Is CL_TRUE if the linker is available.</p> |
| <p class="tableblock"> This can be CL_FALSE for the embedded platform profile only.</p> |
| <p class="tableblock"> This must be CL_TRUE if CL_DEVICE_COMPILER_AVAILABLE is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_EXECUTION_CAPABILITIES</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_exec_ capabilities</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Describes the execution capabilities of the device. |
| This is a bit-field that describes one or more of the following |
| values:</p> |
| <p class="tableblock"> CL_EXEC_KERNEL - The OpenCL device can execute OpenCL kernels.</p> |
| <p class="tableblock"> CL_EXEC_NATIVE_KERNEL - The OpenCL device can execute native |
| kernels.</p> |
| <p class="tableblock"> The mandated minimum capability is: CL_EXEC_KERNEL.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_QUEUE_ON_HOST_PROPERTIES<sup>8</sup></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_command_queue_properties</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Describes the on host command-queue properties supported by the |
| device. |
| This is a bit-field that describes one or more of the following |
| values:</p> |
| <p class="tableblock"> CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE<br> |
| CL_QUEUE_PROFILING_ENABLE</p> |
| <p class="tableblock"> These properties are described in the <a href="#queue-properties-table">Queue Properties</a> table.</p> |
| <p class="tableblock"> The mandated minimum capability is: CL_QUEUE_PROFILING_ENABLE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_command_queue_properties</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Describes the on device command-queue properties supported by the |
| device. |
| This is a bit-field that describes one or more of the following |
| values:</p> |
| <p class="tableblock"> CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE<br> |
| CL_QUEUE_PROFILING_ENABLE</p> |
| <p class="tableblock"> These properties are described in the <a href="#queue-properties-table">Queue Properties</a> table.</p> |
| <p class="tableblock"> The mandated minimum capability is: |
| CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_PROFILING_ENABLE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The size of the device queue in bytes preferred by the |
| implementation. |
| Applications should use this size for the device queue to ensure |
| good performance.</p> |
| <p class="tableblock"> The minimum value is 16 KB</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The max. size of the device queue in bytes. |
| The minimum value is 256 KB for the full profile and 64 KB for the |
| embedded profile</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_ON_DEVICE_QUEUES</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The maximum number of device queues that can be created for this |
| device in a single context.</p> |
| <p class="tableblock"> The minimum value is 1.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_ON_DEVICE_EVENTS</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The maximum number of events in use by a device queue. |
| These refer to events returned by the <code>enqueue_</code> built-in functions |
| to a device queue or user events returned by the <code>create_user_event</code> |
| built-in function that have not been released.</p> |
| <p class="tableblock"> The minimum value is 1024.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_BUILT_IN_KERNELS</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">A semi-colon separated list of built-in kernels supported by the |
| device. |
| An empty string is returned if no built-in kernels are supported by |
| the device.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PLATFORM</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_platform_id</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The platform associated with this device.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_NAME</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Device name string.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_VENDOR</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Vendor name string.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DRIVER_VERSION</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">OpenCL software driver version string. |
| Follows a vendor-specific format.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PROFILE<sup>9</sup></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">OpenCL profile string. |
| Returns the profile name supported by the device. |
| The profile name returned can be one of the following strings:</p> |
| <p class="tableblock"> FULL_PROFILE - if the device supports the OpenCL specification |
| (functionality defined as part of the core specification and does |
| not require any extensions to be supported).</p> |
| <p class="tableblock"> EMBEDDED_PROFILE - if the device supports the OpenCL embedded |
| profile.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_VERSION</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">OpenCL version string. |
| Returns the OpenCL version supported by the device. This version |
| string has the following format:</p> |
| <p class="tableblock"> <em>OpenCL<space><major_version.minor_version><space><vendor-specific |
| information></em></p> |
| <p class="tableblock"> The major_version.minor_version value returned will be 2.2.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_OPENCL_C_VERSION</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">OpenCL C version string. |
| Returns the highest OpenCL C version supported by the compiler for |
| this device that is not of type CL_DEVICE_TYPE_CUSTOM. |
| This version string has the following format:</p> |
| <p class="tableblock"> <em>OpenCL<space>C<space><major_version.minor_version><space><vendor-specific |
| information></em></p> |
| <p class="tableblock"> The major_version.minor_version value returned must be 2.0 if |
| CL_DEVICE_VERSION is OpenCL 2.0.</p> |
| <p class="tableblock"> The major_version.minor_version value returned must be 1.2 if |
| CL_DEVICE_VERSION is OpenCL 1.2.</p> |
| <p class="tableblock"> The major_version.minor_version value returned must be 1.1 if |
| CL_DEVICE_VERSION is OpenCL 1.1.</p> |
| <p class="tableblock"> The major_version.minor_version value returned can be 1.0 or 1.1 if |
| CL_DEVICE_VERSION is OpenCL 1.0.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_EXTENSIONS</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns a space separated list of extension names (the extension |
| names themselves do not contain any spaces) supported by the device. |
| The list of extension names returned can be vendor supported |
| extension names and one or more of the following Khronos approved |
| extension names:</p> |
| <p class="tableblock"> <strong>cl_khr_int64_base_atomics</strong><br> |
| <strong>cl_khr_int64_extended_atomics</strong><br> |
| <strong>cl_khr_fp16</strong><br> |
| <strong>cl_khr_gl_sharing</strong><br> |
| <strong>cl_khr_gl_event</strong><br> |
| <strong>cl_khr_d3d10_sharing</strong><br> |
| <strong>cl_khr_dx9_media_sharing</strong><br> |
| <strong>cl_khr_d3d11_sharing</strong><br> |
| <strong>cl_khr_gl_depth_images</strong><br> |
| <strong>cl_khr_gl_msaa_sharing</strong><br> |
| <strong>cl_khr_initialize_memory</strong><br> |
| <strong>cl_khr_terminate_context</strong><br> |
| <strong>cl_khr_spir</strong><br> |
| <strong>cl_khr_srgb_image_writes</strong></p> |
| <p class="tableblock"> The following approved Khronos extension names must be returned by |
| all devices that support OpenCL C 2.0:</p> |
| <p class="tableblock"> <strong>cl_khr_byte_addressable_store</strong><br> |
| <strong>cl_khr_fp64</strong> (for backward compatibility if double precision is |
| supported)<br> |
| <strong>cl_khr_3d_image_writes</strong><br> |
| <strong>cl_khr_image2d_from_buffer</strong><br> |
| <strong>cl_khr_depth_images</strong></p> |
| <p class="tableblock"> Please refer to the OpenCL 2.0 Extension Specification for a |
| detailed description of these extensions.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PRINTF_BUFFER_SIZE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum size in bytes of the internal buffer that holds the output |
| of printf calls from a kernel. |
| The minimum value for the FULL profile is 1 MB.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PREFERRED_INTEROP_USER_SYNC</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_TRUE if the devices preference is for the user to be |
| responsible for synchronization, when sharing memory objects between |
| OpenCL and other APIs such as DirectX, CL_FALSE if the device / |
| implementation has a performant path for performing synchronization |
| of memory object shared between OpenCL and other APIs such as |
| DirectX.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PARENT_DEVICE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_id</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the cl_device_id of the parent device to which this |
| sub-device belongs. |
| If <em>device</em> is a root-level device, a <code>NULL</code> value is returned.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PARTITION_MAX_SUB_DEVICES</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the maximum number of sub-devices that can be created when a |
| device is partitioned.</p> |
| <p class="tableblock"> The value returned cannot exceed CL_DEVICE_MAX_COMPUTE_UNITS.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PARTITION_PROPERTIES</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_partition_ property[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the list of partition types supported by <em>device</em>. |
| This is an array of cl_device_partition_property values drawn from |
| the following list:</p> |
| <p class="tableblock"> CL_DEVICE_PARTITION_EQUALLY<br> |
| CL_DEVICE_PARTITION_BY_COUNTS<br> |
| CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN</p> |
| <p class="tableblock"> If the device cannot be partitioned (i.e. there is no partitioning |
| scheme supported by the device that will return at least two |
| subdevices), a value of 0 will be returned.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PARTITION_AFFINITY_DOMAIN</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_affinity_ domain</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the list of supported affinity domains for partitioning the |
| device using CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN. |
| This is a bit-field that describes one or more of the following |
| values:</p> |
| <p class="tableblock"> CL_DEVICE_AFFINITY_DOMAIN_NUMA<br> |
| CL_DEVICE_AFFINITY_DOMAIN_L4_CACHE<br> |
| CL_DEVICE_AFFINITY_DOMAIN_L3_CACHE<br> |
| CL_DEVICE_AFFINITY_DOMAIN_L2_CACHE<br> |
| CL_DEVICE_AFFINITY_DOMAIN_L1_CACHE<br> |
| CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE</p> |
| <p class="tableblock"> If the device does not support any affinity domains, a value of 0 |
| will be returned.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PARTITION_TYPE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_partition_ property[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the properties argument specified in <strong>clCreateSubDevices</strong> if |
| device is a sub-device. |
| In the case where the properties argument to <strong>clCreateSubDevices</strong> is |
| CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN, |
| CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE, the affinity domain |
| used to perform the partition will be returned. |
| This can be one of the following values:</p> |
| <p class="tableblock"> CL_DEVICE_AFFINITY_DOMAIN_NUMA<br> |
| CL_DEVICE_AFFINITY_DOMAIN_L4_CACHE<br> |
| CL_DEVICE_AFFINITY_DOMAIN_L3_CACHE<br> |
| CL_DEVICE_AFFINITY_DOMAIN_L2_CACHE<br> |
| CL_DEVICE_AFFINITY_DOMAIN_L1_CACHE</p> |
| <p class="tableblock"> Otherwise the implementation may either return a |
| <em>param_value_size_ret</em> of 0 i.e. there is no partition type |
| associated with device or can return a property value of 0 (where 0 |
| is used to terminate the partition property list) in the memory that |
| <em>param_value</em> points to.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_REFERENCE_COUNT</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the <em>device</em> reference count. |
| If the device is a root-level device, a reference count of one is |
| returned.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_SVM_CAPABILITIES</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_svm_ capabilities</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Describes the various shared virtual memory (a.k.a. SVM) memory |
| allocation types the device supports. |
| Coarse-grain SVM allocations are required to be supported by all |
| OpenCL 2.0 devices. |
| This is a bit-field that describes a combination of the following |
| values:</p> |
| <p class="tableblock"> CL_DEVICE_SVM_COARSE_GRAIN_BUFFER - Support for coarse-grain buffer |
| sharing using <strong>clSVMAlloc</strong>. |
| Memory consistency is guaranteed at synchronization points and the |
| host must use calls to <strong>clEnqueueMapBuffer</strong> and |
| <strong>clEnqueueUnmapMemObject</strong>.</p> |
| <p class="tableblock"> CL_DEVICE_SVM_FINE_GRAIN_BUFFER - Support for fine-grain buffer |
| sharing using <strong>clSVMAlloc</strong>. |
| Memory consistency is guaranteed at synchronization points without |
| need for <strong>clEnqueueMapBuffer</strong> and <strong>clEnqueueUnmapMemObject</strong>.</p> |
| <p class="tableblock"> CL_DEVICE_SVM_FINE_GRAIN_SYSTEM - Support for sharing the host’s |
| entire virtual memory including memory allocated using <strong>malloc</strong>. |
| Memory consistency is guaranteed at synchronization points.</p> |
| <p class="tableblock"> CL_DEVICE_SVM_ATOMICS - Support for the OpenCL 2.0 atomic |
| operations that provide memory consistency across the host and all |
| OpenCL devices supporting fine-grain SVM allocations.</p> |
| <p class="tableblock"> The mandated minimum capability is |
| CL_DEVICE_SVM_COARSE_GRAIN_BUFFER.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the value representing the preferred alignment in bytes for |
| OpenCL 2.0 fine-grained SVM atomic types. |
| This query can return 0 which indicates that the preferred alignment |
| is aligned to the natural size of the type.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the value representing the preferred alignment in bytes for |
| OpenCL 2.0 atomic types to global memory. |
| This query can return 0 which indicates that the preferred alignment |
| is aligned to the natural size of the type.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the value representing the preferred alignment in bytes for |
| OpenCL 2.0 atomic types to local memory. |
| This query can return 0 which indicates that the preferred alignment |
| is aligned to the natural size of the type.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_NUM_SUB_GROUPS</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum number of sub-groups in a work-group that a device is |
| capable of executing on a single compute unit, for any given |
| kernel-instance running on the device. |
| The minimum value is 1. |
| (Refer also to <strong>clGetKernelSubGroupInfo</strong>.)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_TRUE if this device supports independent forward progress of |
| sub-groups, CL_FALSE otherwise. |
| If <strong>cl_khr_subgroups</strong> is supported by the device this must return |
| CL_TRUE.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">4</dt> |
| <dd> |
| <p>A kernel that uses an image argument with the write_only or read_write |
| image qualifier may result in additional read_only images resources being |
| created internally by an implementation. |
| The internally created read_only image resources will count against the max |
| supported read image arguments given by CL_DEVICE_MAX_READ_IMAGE_ARGS. |
| Enqueuing a kernel that requires more images than the implementation can |
| support will result in a CL_OUT_OF_RESOURCES error being returned.</p> |
| </dd> |
| <dt class="hdlist1">5</dt> |
| <dd> |
| <p>NOTE: <strong>CL_DEVICE_MAX_WRITE_IMAGE_ARGS</strong> is only there for backward |
| compatibility. |
| <strong>CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS</strong> should be used instead.</p> |
| </dd> |
| <dt class="hdlist1">6</dt> |
| <dd> |
| <p>The optional rounding modes should be included as a device capability |
| only if it is supported natively. |
| All explicit conversion functions with specific rounding modes must |
| still operate correctly.</p> |
| </dd> |
| <dt class="hdlist1">7</dt> |
| <dd> |
| <p>The optional rounding modes should be included as a device capability |
| only if it is supported natively. |
| All explicit conversion functions with specific rounding modes must |
| still operate correctly.</p> |
| </dd> |
| <dt class="hdlist1">8</dt> |
| <dd> |
| <p>CL_DEVICE_QUEUE_PROPERTIES is deprecated and replaced by |
| CL_DEVICE_QUEUE_ON_HOST_PROPERTIES.</p> |
| </dd> |
| <dt class="hdlist1">9</dt> |
| <dd> |
| <p>The platform profile returns the profile that is implemented by the |
| OpenCL framework. |
| If the platform profile returned is FULL_PROFILE, the OpenCL framework |
| will support devices that are FULL_PROFILE and may also support devices |
| that are EMBEDDED_PROFILE. |
| The compiler must be available for all devices i.e. |
| CL_DEVICE_COMPILER_AVAILABLE is CL_TRUE. |
| If the platform profile returned is EMBEDDED_PROFILE, then devices that |
| are only EMBEDDED_PROFILE are supported.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>The device queries described in the <a href="#device-queries-table">Device Queries</a> |
| table should return the same information for a root-level device i.e. a |
| device returned by <strong>clGetDeviceIDs</strong> and any sub-devices created from this |
| device except for the following queries:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_DEVICE_GLOBAL_MEM_CACHE_SIZE</p> |
| </li> |
| <li> |
| <p>CL_DEVICE_BUILT_IN_KERNELS</p> |
| </li> |
| <li> |
| <p>CL_DEVICE_PARENT_DEVICE</p> |
| </li> |
| <li> |
| <p>CL_DEVICE_PARTITION_TYPE</p> |
| </li> |
| <li> |
| <p>CL_DEVICE_REFERENCE_COUNT</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clGetDeviceInfo</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_DEVICE if <em>device</em> is not valid.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is not one of the supported values or |
| if size in bytes specified by <em>param_value_size</em> is < size of return |
| type as specified in the <a href="#device-queries-table">Device Queries</a> table |
| and <em>param_value</em> is not a <code>NULL</code> value or if <em>param_name</em> is a value |
| that is available as an extension and the corresponding extension is not |
| supported by the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetDeviceAndHostTimer(cl_device_id device, |
| cl_ulong* device_timestamp, |
| cl_ulong* host_timestamp)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Returns a reasonably synchronized pair of timestamps from the device timer |
| and the host timer as seen by <em>device</em>. |
| Implementations may need to execute this query with a high latency in order |
| to provide reasonable synchronization of the timestamps. |
| The host timestamp and device timestamp returned by this function and |
| <strong>clGetHostTimer</strong> each have an implementation defined timebase. |
| The timestamps will always be in their respective timebases regardless of |
| which query function is used. |
| The timestamp returned from <strong>clGetEventProfilingInfo</strong> for an event on a |
| device and a device timestamp queried from the same device will always be in |
| the same timebase.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>device</em> is a device returned by <strong>clGetDeviceIDs</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>device_timestamp</em> will be updated with the value of the device timer in |
| nanoseconds. |
| The resolution of the timer is the same as the device profiling timer |
| returned by <strong>clGetDeviceInfo</strong> and the CL_DEVICE_PROFILING_TIMER_RESOLUTION |
| query.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>host_timestamp</em> will be updated with the value of the host timer in |
| nanoseconds at the closest possible point in time to that at which |
| <em>device_timer</em> was returned. |
| The resolution of the timer may be queried via <strong>clGetPlatformInfo</strong> and the |
| flag CL_PLATFORM_HOST_TIMER_RESOLUTION.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clGetDeviceAndHostTimer</strong> will return CL_SUCCESS with a time value in |
| <em>host_timestamp</em> if provided. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_DEVICE if <em>device</em> is not a valid OpenCL device.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>host_timestamp</em> or <em>device_timestamp</em> is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetHostTimer(cl_device_id device, |
| cl_ulong* host_timestamp)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Return the current value of the host clock as seen by <em>device</em>. |
| This value is in the same timebase as the host_timestamp returned from |
| <strong>clGetDeviceAndHostTimer</strong>. |
| The implementation will return with as low a latency as possible to allow a |
| correlation with a subsequent application sampled time. |
| The host timestamp and device timestamp returned by this function and |
| <strong>clGetDeviceAndHostTimer</strong> each have an implementation defined timebase. |
| The timestamps will always be in their respective timebases regardless of |
| which query function is used. |
| The timestamp returned from <strong>clGetEventProfilingInfo</strong> for an event on a |
| device and a device timestamp queried from the same device will always be in |
| the same timebase.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>device</em> is a device returned by <strong>clGetDeviceIDs</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>host_timestamp</em> will be updated with the value of the current timer in |
| nanoseconds. |
| The resolution of the timer may be queried via <strong>clGetPlatformInfo</strong> and the |
| flag CL_PLATFORM_HOST_TIMER_RESOLUTION.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clGetHostTimer</strong> will return CL_SUCCESS with a time value in |
| <em>host_timestamp</em> if provided. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_DEVICE if <em>device</em> is not a valid OpenCL device.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>host_timestamp</em> is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_partitioning_a_device">4.3. Partitioning a Device</h3> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clCreateSubDevices(cl_device_id in_device, |
| <span class="directive">const</span> cl_device_partition_property *properties, |
| cl_uint num_devices, |
| cl_device_id *out_devices, |
| cl_uint *num_devices_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>creates an array of sub-devices that each reference a non-intersecting set |
| of compute units within in_device, according to a partition scheme given by |
| <em>properties</em>. |
| The output sub-devices may be used in every way that the root (or parent) |
| device can be used, including creating contexts, building programs, further |
| calls to <strong>clCreateSubDevices</strong> and creating command-queues. |
| When a command-queue is created against a sub-device, the commands enqueued |
| on the queue are executed only on the sub-device.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>in_device</em> is the device to be partitioned.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>properties</em> specifies how <em>in_device</em> is to be partition described by a |
| partition name and its corresponding value. |
| Each partition name is immediately followed by the corresponding desired |
| value. |
| The list is terminated with 0. |
| The list of supported partitioning schemes is described in the |
| <a href="#subdevice-partition-table">Subdevice Partition</a> table. |
| Only one of the listed partitioning schemes can be specified in |
| <em>properties</em>.</p> |
| </div> |
| <table id="subdevice-partition-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 6. <em>List of supported partition schemes by</em> <strong>clCreateSubDevices</strong></caption> |
| <colgroup> |
| <col style="width: 30%;"> |
| <col style="width: 20%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_device_partition_property enum</strong></th> |
| <th class="tableblock halign-left valign-top">Partition value</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_PARTITION_EQUALLY</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Split the aggregate device into as many smaller aggregate devices as |
| can be created, each containing <em>n</em> compute units. |
| The value <em>n</em> is passed as the value accompanying this property. |
| If <em>n</em> does not divide evenly into |
| CL_DEVICE_PARTITION_MAX_COMPUTE_UNITS, then the remaining compute |
| units are not used.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_PARTITION_BY_COUNTS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This property is followed by a |
| CL_DEVICE_PARTITION_BY_COUNTS_LIST_END terminated list of compute |
| unit counts. |
| For each non-zero count <em>m</em> in the list, a sub-device is created |
| with <em>m</em> compute units in it. |
| CL_DEVICE_PARTITION_BY_COUNTS_LIST_END is defined to be 0.</p> |
| <p class="tableblock"> The number of non-zero count entries in the list may not exceed |
| CL_DEVICE_PARTITION_MAX_SUB_DEVICES.</p> |
| <p class="tableblock"> The total number of compute units specified may not exceed |
| CL_DEVICE_PARTITION_MAX_COMPUTE_UNITS.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_affinity_ domain</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Split the device into smaller aggregate devices containing one or |
| more compute units that all share part of a cache hierarchy. |
| The value accompanying this property may be drawn from the following |
| list:</p> |
| <p class="tableblock"> CL_DEVICE_AFFINITY_DOMAIN_NUMA - Split the device into sub-devices |
| comprised of compute units that share a NUMA node.</p> |
| <p class="tableblock"> CL_DEVICE_AFFINITY_DOMAIN_L4_CACHE - Split the device into |
| sub-devices comprised of compute units that share a level 4 data |
| cache.</p> |
| <p class="tableblock"> CL_DEVICE_AFFINITY_DOMAIN_L3_CACHE - Split the device into |
| sub-devices comprised of compute units that share a level 3 data |
| cache.</p> |
| <p class="tableblock"> CL_DEVICE_AFFINITY_DOMAIN_L2_CACHE - Split the device into |
| sub-devices comprised of compute units that share a level 2 data |
| cache.</p> |
| <p class="tableblock"> CL_DEVICE_AFFINITY_DOMAIN_L1_CACHE - Split the device into |
| sub-devices comprised of compute units that share a level 1 data |
| cache.</p> |
| <p class="tableblock"> CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE - Split the device |
| along the next partitionable affinity domain. |
| The implementation shall find the first level along which the device |
| or sub-device may be further subdivided in the order NUMA, L4, L3, |
| L2, L1, and partition the device into sub-devices comprised of |
| compute units that share memory subsystems at this level.</p> |
| <p class="tableblock"> The user may determine what happened by calling |
| <strong>clGetDeviceInfo</strong>(CL_DEVICE_PARTITION_TYPE) on the sub-devices.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p><em>num_devices</em> is the size of memory pointed to by <em>out_devices</em> specified as |
| the number of cl_device_id entries.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>out_devices</em> is the buffer where the OpenCL sub-devices will be returned. |
| If <em>out_devices</em> is <code>NULL</code>, this argument is ignored. |
| If <em>out_devices</em> is not <code>NULL</code>, <em>num_devices</em> must be greater than or equal |
| to the number of sub-devices that <em>device</em> may be partitioned into according |
| to the partitioning scheme specified in <em>properties</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>num_devices_ret</em> returns the number of sub-devices that <em>device</em> may be |
| partitioned into according to the partitioning scheme specified in |
| <em>properties</em>. |
| If <em>num_devices_ret</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreateSubDevices</strong> returns CL_SUCCESS if the partition is created |
| successfully. |
| Otherwise, it returns a <code>NULL</code> value with the following error values |
| returned in <em>errcode_ret</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_DEVICE if <em>in_device</em> is not valid.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if values specified in <em>properties</em> are not valid or if |
| values specified in <em>properties</em> are valid but not supported by the |
| device.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>out_devices</em> is not <code>NULL</code> and <em>num_devices</em> is |
| less than the number of sub-devices created by the partition scheme.</p> |
| </li> |
| <li> |
| <p>CL_DEVICE_PARTITION_FAILED if the partition name is supported by the |
| implementation but in_device could not be further partitioned.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_DEVICE_PARTITION_COUNT if the partition name specified in |
| <em>properties</em> is CL_DEVICE_PARTITION_BY_COUNTS and the number of |
| sub-devices requested exceeds CL_DEVICE_PARTITION_MAX_SUB_DEVICES or the |
| total number of compute units requested exceeds |
| CL_DEVICE_PARTITION_MAX_COMPUTE_UNITS for <em>in_device</em>, or the number of |
| compute units requested for one or more sub-devices is less than zero or |
| the number of sub-devices requested exceeds |
| CL_DEVICE_PARTITION_MAX_COMPUTE_UNITS for <em>in_device</em>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>A few examples that describe how to specify partition properties in |
| <em>properties</em> argument to <strong>clCreateSubDevices</strong> are given below:</p> |
| </div> |
| <div class="paragraph"> |
| <p>To partition a device containing 16 compute units into two sub-devices, each |
| containing 8 compute units, pass the following in <em>properties</em>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">{ CL_DEVICE_PARTITION_EQUALLY, <span class="integer">8</span>, <span class="integer">0</span> }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>To partition a device with four compute units into two sub-devices with one |
| sub-device containing 3 compute units and the other sub-device 1 compute |
| unit, pass the following in properties argument:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">{ CL_DEVICE_PARTITION_BY_COUNTS, |
| <span class="integer">3</span>, <span class="integer">1</span>, CL_DEVICE_PARTITION_BY_COUNTS_LIST_END, <span class="integer">0</span> }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>To split a device along the outermost cache line (if any), pass the |
| following in properties argument:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">{ CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN, |
| CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE, |
| <span class="integer">0</span> }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clRetainDevice(cl_device_id device)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>increments the <em>device</em> reference count if <em>device</em> is a valid sub-device |
| created by a call to <strong>clCreateSubDevices</strong>. |
| If <em>device</em> is a root level device i.e. a cl_device_id returned by |
| <strong>clGetDeviceIDs</strong>, the <em>device</em> reference count remains unchanged. |
| <strong>clRetainDevice</strong> returns CL_SUCCESS if the function is executed successfully |
| or the device is a root-level device. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_DEVICE if <em>device</em> is not a valid sub-device created by a |
| call to <strong>clCreateSubDevices</strong>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clReleaseDevice(cl_device_id device)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>decrements the <em>device</em> reference count if device is a valid sub-device |
| created by a call to <strong>clCreateSubDevices</strong>. |
| If <em>device</em> is a root level device i.e. a cl_device_id returned by |
| <strong>clGetDeviceIDs</strong>, the <em>device</em> reference count remains unchanged. |
| <strong>clReleaseDevice</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_DEVICE if <em>device</em> is not a valid sub-device created by a |
| call to <strong>clCreateSubDevices</strong>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>After the <em>device</em> reference count becomes zero and all the objects attached |
| to <em>device</em> (such as command-queues) are released, the <em>device</em> object is |
| deleted. |
| Using this function to release a reference that was not obtained by creating |
| the object or by calling <strong>clRetainDevice</strong> causes undefined behavior.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_contexts">4.4. Contexts</h3> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_context clCreateContext(<span class="directive">const</span> cl_context_properties *properties, |
| cl_uint num_devices, |
| <span class="directive">const</span> cl_device_id *devices, |
| <span class="directive">void</span>(CL_CALLBACK *pfn_notify) |
| (<span class="directive">const</span> <span class="predefined-type">char</span> *errinfo, |
| <span class="directive">const</span> <span class="directive">void</span> *private_info, |
| size_t cb, |
| <span class="directive">void</span> *user_data), |
| <span class="directive">void</span> *user_data, |
| cl_int *errcode_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>creates an OpenCL context. |
| An OpenCL context is created with one or more devices. |
| Contexts are used by the OpenCL runtime for managing objects such as |
| command-queues, memory, program and kernel objects and for executing kernels |
| on one or more devices specified in the context.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>properties</em> specifies a list of context property names and their |
| corresponding values. |
| Each property name is immediately followed by the corresponding desired |
| value. |
| The list is terminated with 0. |
| The list of supported properties is described in the |
| <a href="#context-properties-table">Context Properties</a> table. |
| <em>properties</em> can be <code>NULL</code> in which case the platform that is selected is |
| implementation-defined.</p> |
| </div> |
| <table id="context-properties-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 7. <em>List of supported properties by</em> <strong>clCreateContext</strong></caption> |
| <colgroup> |
| <col style="width: 34%;"> |
| <col style="width: 33%;"> |
| <col style="width: 33%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_context_properties enum</strong></th> |
| <th class="tableblock halign-left valign-top">Property value</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_PLATFORM</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_platform_id</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Specifies the platform to use.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_INTEROP_USER_SYNC</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Specifies whether the user is responsible for synchronization |
| between OpenCL and other APIs. |
| Please refer to the specific sections in the OpenCL 2.0 extension |
| specification that describe sharing with other APIs for restrictions |
| on using this flag.</p> |
| <p class="tableblock"> If CL_CONTEXT_INTEROP_USER_SYNC is not specified, a default of |
| CL_FALSE is assumed.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p><em>num_devices</em> is the number of devices specified in the <em>devices</em> argument.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>devices</em> is a pointer to a list of unique devices<sup>10</sup> returned by |
| <strong>clGetDeviceIDs</strong> or sub-devices created by <strong>clCreateSubDevices</strong> for a |
| platform.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">10</dt> |
| <dd> |
| <p>Duplicate devices specified in <em>devices</em> are ignored.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p><em>pfn_notify</em> is a callback function that can be registered by the |
| application. |
| This callback function will be used by the OpenCL implementation to report |
| information on errors during context creation as well as errors that occur |
| at runtime in this context. |
| This callback function may be called asynchronously by the OpenCL |
| implementation. |
| It is the applications responsibility to ensure that the callback function |
| is thread-safe. |
| The parameters to this callback function are:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><em>errinfo</em> is a pointer to an error string.</p> |
| </li> |
| <li> |
| <p><em>private_info</em> and <em>cb</em> represent a pointer to binary data that is |
| returned by the OpenCL implementation that can be used to log additional |
| information helpful in debugging the error.</p> |
| </li> |
| <li> |
| <p><em>user_data</em> is a pointer to user supplied data.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>pfn_notify</em> is <code>NULL</code>, no callback function is registered.</p> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| There are a number of cases where error notifications need to be |
| delivered due to an error that occurs outside a context. |
| Such notifications may not be delivered through the <em>pfn_notify</em> callback. |
| Where these notifications go is implementation-defined. |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p><em>user_data</em> will be passed as the <em>user_data</em> argument when <em>pfn_notify</em> is |
| called. |
| <em>user_data</em> can be <code>NULL</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>errcode_ret</em> will return an appropriate error code. |
| If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreateContext</strong> returns a valid non-zero context and <em>errcode_ret</em> is set |
| to CL_SUCCESS if the context is created successfully. |
| Otherwise, it returns a <code>NULL</code> value with the following error values |
| returned in <em>errcode_ret</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_PLATFORM if <em>properties</em> is <code>NULL</code> and no platform could be |
| selected or if platform value specified in <em>properties</em> is not a valid |
| platform.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_PROPERTY if context property name in <em>properties</em> is not a |
| supported property name, if the value specified for a supported property |
| name is not valid, or if the same property name is specified more than |
| once.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>devices</em> is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>num_devices</em> is equal to zero.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>pfn_notify</em> is <code>NULL</code> but <em>user_data</em> is not |
| <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_DEVICE if <em>devices</em> contains an invalid device.</p> |
| </li> |
| <li> |
| <p>CL_DEVICE_NOT_AVAILABLE if a device in <em>devices</em> is currently not |
| available even though the device was returned by <strong>clGetDeviceIDs</strong>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function<sup>11</sup></p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_context clCreateContextFromType(<span class="directive">const</span> cl_context_properties *properties, |
| cl_device_type device_type, |
| <span class="directive">void</span>(CL_CALLBACK *pfn_notify)( |
| (<span class="directive">const</span> <span class="predefined-type">char</span> *errinfo, |
| <span class="directive">const</span> <span class="directive">void</span> *private_info, |
| size_t cb, |
| <span class="directive">void</span> *user_data), |
| <span class="directive">void</span> *user_data, |
| cl_int *errcode_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>creates an OpenCL context from a device type that identifies the specific |
| device(s) to use. |
| Only devices that are returned by <strong>clGetDeviceIDs</strong> for <em>device_type</em> are |
| used to create the context. |
| The context does not reference any sub-devices that may have been created |
| from these devices.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>properties</em> specifies a list of context property names and their |
| corresponding values. |
| Each property name is immediately followed by the corresponding desired |
| value. |
| The list of supported properties is described in the |
| <a href="#context-properties-table">Context Properties</a> table. |
| <em>properties</em> can also be <code>NULL</code> in which case the platform that is selected |
| is implementation-defined.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>device_type</em> is a bit-field that identifies the type of device and is |
| described in the <a href="#device-categories-table">Device Categories</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>pfn_notify</em> and <em>user_data</em> are described in <strong>clCreateContext</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>errcode_ret</em> will return an appropriate error code. |
| If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreateContextFromType</strong> returns a valid non-zero context and <em>errcode_ret</em> |
| is set to CL_SUCCESS if the context is created successfully. |
| Otherwise, it returns a <code>NULL</code> value with the following error values |
| returned in <em>errcode_ret</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_PLATFORM if <em>properties</em> is <code>NULL</code> and no platform could be |
| selected or if platform value specified in <em>properties</em> is not a valid |
| platform.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_PROPERTY if context property name in <em>properties</em> is not a |
| supported property name, if the value specified for a supported property |
| name is not valid, or if the same property name is specified more than |
| once.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>pfn_notify</em> is <code>NULL</code> but <em>user_data</em> is not |
| <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_DEVICE_TYPE if <em>device_type</em> is not a valid value.</p> |
| </li> |
| <li> |
| <p>CL_DEVICE_NOT_AVAILABLE if no devices that match <em>device_type</em> and |
| property values specified in <em>properties</em> are currently available.</p> |
| </li> |
| <li> |
| <p>CL_DEVICE_NOT_FOUND if no devices that match <em>device_type</em> and property |
| values specified in <em>properties</em> were found.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">11</dt> |
| <dd> |
| <p><strong>clCreateContextfromType</strong> may return all or a subset of the actual |
| physical devices present in the platform and that match device_type.</p> |
| </dd> |
| </dl> |
| </div> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clRetainContext(cl_context context)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>increments the <em>context</em> reference count. |
| <strong>clRetainContext</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_CONTEXT if <em>context</em> is not a valid OpenCL context.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreateContext</strong> and <strong>clCreateContextFromType</strong> perform an implicit retain. |
| This is very helpful for 3<sup>rd</sup> party libraries, which typically get a |
| context passed to them by the application. |
| However, it is possible that the application may delete the context without |
| informing the library. |
| Allowing functions to attach to (i.e. retain) and release a context solves |
| the problem of a context being used by a library no longer being valid.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clReleaseContext(cl_context context)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>decrements the <em>context</em> reference count. |
| <strong>clReleaseContext</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_CONTEXT if <em>context</em> is not a valid OpenCL context.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>After the <em>context</em> reference count becomes zero and all the objects |
| attached to <em>context</em> (such as memory objects, command-queues) are released, |
| the <em>context</em> is deleted. |
| Using this function to release a reference that was not obtained by creating |
| the object or by calling <strong>clRetainContext</strong> causes undefined behavior.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetContextInfo(cl_context context, |
| cl_context_info param_name, |
| size_t param_value_size, |
| <span class="directive">void</span> *param_value, |
| size_t *param_value_size_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>can be used to query information about a context.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>context</em> specifies the OpenCL context being queried.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_name</em> is an enumeration constant that specifies the information to |
| query.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value</em> is a pointer to memory where the appropriate result being |
| queried is returned. |
| If <em>param_value</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size</em> specifies the size in bytes of memory pointed to by |
| <em>param_value</em>. |
| This size must be greater than or equal to the size of return type as |
| described in the <a href="#context-info-table">Context Attributes</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size_ret</em> returns the actual size in bytes of data being |
| queried by <em>param_name</em>. |
| If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The list of supported <em>param_name</em> values and the information returned in |
| <em>param_value</em> by <strong>clGetContextInfo</strong> is described in the |
| <a href="#context-info-table">Context Attributes</a> table.</p> |
| </div> |
| <table id="context-info-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 8. List of supported param_names by <strong>clGetContextInfo</strong></caption> |
| <colgroup> |
| <col style="width: 34%;"> |
| <col style="width: 33%;"> |
| <col style="width: 33%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_context_info</strong></th> |
| <th class="tableblock halign-left valign-top">Return Type</th> |
| <th class="tableblock halign-left valign-top">Information returned in param_value</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_REFERENCE_COUNT</strong><sup>12</sup></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the <em>context</em> reference count.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_NUM_DEVICES</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the number of devices in <em>context</em>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_DEVICES</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_id[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the list of devices and sub-devices in <em>context</em>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_PROPERTIES</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_context_properties[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the properties argument specified in <strong>clCreateContext</strong> or |
| <strong>clCreateContextFromType</strong>.</p> |
| <p class="tableblock"> If the <em>properties</em> argument specified in <strong>clCreateContext</strong> or |
| <strong>clCreateContextFromType</strong> used to create <em>context</em> is not <code>NULL</code>, the |
| implementation must return the values specified in the properties |
| argument.</p> |
| <p class="tableblock"> If the <em>properties</em> argument specified in <strong>clCreateContext</strong> or |
| <strong>clCreateContextFromType</strong> used to create <em>context</em> is <code>NULL</code>, the |
| implementation may return either a <em>param_value_size_ret</em> of 0 |
| i.e. there is no context property value to be returned or can return |
| a context property value of 0 (where 0 is used to terminate the |
| context properties list) in the memory that <em>param_value</em> points |
| to.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">12</dt> |
| <dd> |
| <p>The reference count returned should be considered immediately stale. |
| It is unsuitable for general use in applications. |
| This feature is provided for identifying memory leaks.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clGetContextInfo</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is not one of the supported values or |
| if size in bytes specified by <em>param_value_size</em> is < size of return |
| type as specified in the <a href="#context-info-table">Context Attributes</a> |
| table and <em>param_value</em> is not a <code>NULL</code> value.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="opencl-runtime">5. The OpenCL Runtime</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>In this section we describe the API calls that manage OpenCL objects such as |
| command-queues, memory objects, program objects, kernel objects for kernel |
| functions in a program and calls that allow you to enqueue commands to a |
| command-queue such as executing a kernel, reading, or writing a memory |
| object.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="_command_queues">5.1. Command Queues</h3> |
| <div class="paragraph"> |
| <p>OpenCL objects such as memory, program and kernel objects are created using |
| a context. |
| Operations on these objects are performed using a command-queue. |
| The command-queue can be used to queue a set of operations (referred to as |
| commands) in order. |
| Having multiple command-queues allows applications to queue multiple |
| independent commands without requiring synchronization. |
| Note that this should work as long as these objects are not being shared. |
| Sharing of objects across multiple command-queues will require the |
| application to perform appropriate synchronization. |
| This is described in <a href="#shared-opencl-objects">Shared OpenCL Objects</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_command_queue clCreateCommandQueueWithProperties( |
| cl_context context, |
| cl_device_id device, |
| <span class="directive">const</span> cl_queue_properties *properties, |
| cl_int *errcode_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>creates a host or device command-queue on a specific device.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>context</em> must be a valid OpenCL context.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>device</em> must be a device or sub-device associated with <em>context</em>. |
| It can either be in the list of devices and sub-devices specified when |
| <em>context</em> is created using <strong>clCreateContext</strong> or be a root device with the |
| same device type as specified when <em>context</em> is created using |
| <strong>clCreateContextFromType</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>properties</em> specifies a list of properties for the command-queue and their |
| corresponding values. |
| Each property name is immediately followed by the corresponding desired |
| value. |
| The list is terminated with 0. |
| The list of supported properties is described in the table below. |
| If a supported property and its value is not specified in <em>properties</em>, its |
| default value will be used. |
| <em>properties</em> can be <code>NULL</code> in which case the default values for supported |
| command-queue properties will be used.</p> |
| </div> |
| <table id="queue-properties-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 9. List of supported cl_queue_properties values and description</caption> |
| <colgroup> |
| <col style="width: 34%;"> |
| <col style="width: 33%;"> |
| <col style="width: 33%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>Queue Properties</strong></th> |
| <th class="tableblock halign-left valign-top">Property Value</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_QUEUE_PROPERTIES</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_bitfield</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This is a bitfield and can be set to a combination of the following |
| values:</p> |
| <p class="tableblock"> CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE - Determines whether the |
| commands queued in the command-queue are executed in-order or |
| out-of-order. |
| If set, the commands in the command-queue are executed out-of-order. |
| Otherwise, commands are executed in-order.</p> |
| <p class="tableblock"> CL_QUEUE_PROFILING_ENABLE - Enable or disable profiling of commands |
| in the command-queue. |
| If set, the profiling of commands is enabled. |
| Otherwise profiling of commands is disabled.</p> |
| <p class="tableblock"> CL_QUEUE_ON_DEVICE - Indicates that this is a device queue. |
| If CL_QUEUE_ON_DEVICE is set, |
| CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE<sup>1</sup> must also be set.</p> |
| <p class="tableblock"> CL_QUEUE_ON_DEVICE_DEFAULT<sup>2</sup> --indicates that this is the default |
| device queue. |
| This can only be used with CL_QUEUE_ON_DEVICE.</p> |
| <p class="tableblock"> If CL_QUEUE_PROPERTIES is not specified an in-order host command |
| queue is created for the specified device</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_QUEUE_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Specifies the size of the device queue in bytes.</p> |
| <p class="tableblock"> This can only be specified if CL_QUEUE_ON_DEVICE is set in |
| CL_QUEUE_PROPERTIES. |
| This must be a value ≤ CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE.</p> |
| <p class="tableblock"> For best performance, this should be ≤ |
| CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE.</p> |
| <p class="tableblock"> If CL_QUEUE_SIZE is not specified, the device queue is created with |
| CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE as the size of the queue.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">1</dt> |
| <dd> |
| <p>Only out-of-order device queues are supported.</p> |
| </dd> |
| <dt class="hdlist1">2</dt> |
| <dd> |
| <p>The application must create the default device queue if any kernels |
| containing calls to get_default_queue are enqueued. |
| There can only be one default device queue for each device within a |
| context. |
| <strong>clCreateCommandQueueWithProperties</strong> with CL_QUEUE_PROPERTIES set to |
| CL_QUEUE_ON_DEVICE or CL_QUEUE_ON_DEVICE_DEFAULT will return the default |
| device queue that has already been created and increment its retain |
| count by 1.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p><em>errcode_ret</em> will return an appropriate error code. |
| If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreateCommandQueueWithProperties</strong> returns a valid non-zero command-queue |
| and <em>errcode_ret</em> is set to CL_SUCCESS if the command-queue is created |
| successfully. |
| Otherwise, it returns a <code>NULL</code> value with one of the following error values |
| returned in <em>errcode_ret</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_DEVICE if <em>device</em> is not a valid device or is not associated |
| with <em>context</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if values specified in <em>properties</em> are not valid.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_QUEUE_PROPERTIES if values specified in <em>properties</em> are |
| valid but are not supported by the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clSetDefaultDeviceCommandQueue(cl_context context, |
| cl_device_id device, |
| cl_command_queue command_queue)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>replaces the default command queue on the <em>device</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clSetDefaultDeviceCommandQueue</strong> returns CL_SUCCESS if the function is |
| executed successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_DEVICE if <em>device</em> is not a valid device or is not associated |
| with <em>context</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid command-queue |
| for <em>device</em>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clSetDefaultDeviceCommandQueue</strong> may be used to replace a default device |
| command queue created with <strong>clCreateCommandQueueWithProperties</strong> and the |
| CL_QUEUE_ON_DEVICE_DEFAULT flag.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clRetainCommandQueue(cl_command_queue command_queue)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>increments the <em>command_queue</em> reference count. |
| <strong>clRetainCommandQueue</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreateCommandQueueWithProperties</strong> performs an implicit retain. |
| This is very helpful for 3<sup>rd</sup> party libraries, which typically get a |
| command-queue passed to them by the application. |
| However, it is possible that the application may delete the command-queue |
| without informing the library. |
| Allowing functions to attach to (i.e. retain) and release a command-queue |
| solves the problem of a command-queue being used by a library no longer |
| being valid.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clReleaseCommandQueue(cl_command_queue command_queue)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>decrements the <em>command_queue</em> reference count. |
| <strong>clReleaseCommandQueue</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>After the <em>command_queue</em> reference count becomes zero and all commands |
| queued to <em>command_queue</em> have finished (eg. |
| kernel-instances, memory object updates etc.), the command-queue is deleted.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clReleaseCommandQueue</strong> performs an implicit flush to issue any previously |
| queued OpenCL commands in <em>command_queue</em>. |
| Using this function to release a reference that was not obtained by creating |
| the object or by calling <strong>clRetainCommandQueue</strong> causes undefined behavior.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetCommandQueueInfo(cl_command_queue command_queue, |
| cl_command_queue_info param_name, |
| size_t param_value_size, |
| <span class="directive">void</span> *param_value, |
| size_t *param_value_size_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>can be used to query information about a command-queue.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> specifies the command-queue being queried.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_name</em> specifies the information to query.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value</em> is a pointer to memory where the appropriate result being |
| queried is returned. |
| If <em>param_value</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to |
| by <em>param_value</em>. |
| This size must be ≥ size of return type as described in the |
| <a href="#command-queue-param-table">Command Queue Parameter</a> table. |
| If <em>param_value</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size_ret</em> returns the actual size in bytes of data being |
| queried by <em>param_name</em>. |
| If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The list of supported <em>param_name</em> values and the information returned in |
| <em>param_value</em> by <strong>clGetCommandQueueInfo</strong> is described in the |
| <a href="#command-queue-param-table">Command Queue Parameter</a> table.</p> |
| </div> |
| <table id="command-queue-param-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 10. List of supported param_names by <strong>clGetCommandQueueInfo</strong></caption> |
| <colgroup> |
| <col style="width: 34%;"> |
| <col style="width: 33%;"> |
| <col style="width: 33%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_command_queue_info</strong></th> |
| <th class="tableblock halign-left valign-top">Return Type</th> |
| <th class="tableblock halign-left valign-top">Information returned in param_value</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_QUEUE_CONTEXT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_context</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the context specified when the command-queue is created.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_QUEUE_DEVICE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_id</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the device specified when the command-queue is created.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_QUEUE_REFERENCE_COUNT</strong><sup>3</sup></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the command-queue reference count.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_QUEUE_PROPERTIES</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_command_queue_properties</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the currently specified properties for the command-queue. |
| These properties are specified by the value associated with the |
| CL_COMMAND_QUEUE_PROPERTIES passed in <em>properties</em> argument in |
| <strong>clCreateCommandQueueWithProperties.</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_QUEUE_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the currently specified size for the device command-queue. |
| This query is only supported for device command queues.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_QUEUE_DEVICE_DEFAULT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_command_queue</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the current default command queue for the underlying device.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">3</dt> |
| <dd> |
| <p>The reference count returned should be considered immediately stale. |
| It is unsuitable for general use in applications. |
| This feature is provided for identifying memory leaks.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clGetCommandQueueInfo</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is not one of the supported values or |
| if size in bytes specified by <em>param_value_size</em> is < size of return |
| type as specified in the <a href="#command-queue-param-table">Command Queue |
| Parameter</a> table, and <em>param_value</em> is not a <code>NULL</code> value.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>It is possible that a device(s) becomes unavailable after a context and |
| command-queues that use this device(s) have been created and commands have |
| been queued to command-queues. |
| In this case the behavior of OpenCL API calls that use this context (and |
| command-queues) are considered to be implementation-defined. |
| The user callback function, if specified, when the context is created can be |
| used to record appropriate information in the <em>errinfo</em>, <em>private_info</em> |
| arguments passed to the callback function when the device becomes |
| unavailable.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_buffer_objects">5.2. Buffer Objects</h3> |
| <div class="paragraph"> |
| <p>A <em>buffer</em> object stores a one-dimensional collection of elements. |
| Elements of a <em>buffer</em> object can be a scalar data type (such as an int, |
| float), vector data type, or a user-defined structure.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="_creating_buffer_objects">5.2.1. Creating Buffer Objects</h4> |
| <div class="paragraph"> |
| <p>A <strong>buffer object</strong> is created using the following function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_mem clCreateBuffer(cl_context context, |
| cl_mem_flags flags, |
| size_t size, |
| <span class="directive">void</span> *host_ptr, |
| cl_int *errcode_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><em>context</em> is a valid OpenCL context used to create the buffer object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>flags</em> is a bit-field that is used to specify allocation and usage |
| information such as the memory arena that should be used to allocate the |
| buffer object and how it will be used. |
| The <a href="#memory-flags-table">Memory Flags</a> table describes the possible values |
| for <em>flags</em>. |
| If value specified for <em>flags</em> is 0, the default is used which is |
| CL_MEM_READ_WRITE.</p> |
| </div> |
| <table id="memory-flags-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 11. List of supported cl_mem_flags values</caption> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_mem_flags</strong></th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_READ_WRITE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the memory object will be read |
| and written by a kernel. |
| This is the default.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_WRITE_ONLY</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the memory object will be |
| written but not read by a kernel.</p> |
| <p class="tableblock"> Reading from a buffer or image object created with CL_MEM_WRITE_ONLY |
| inside a kernel is undefined.</p> |
| <p class="tableblock"> CL_MEM_READ_WRITE and CL_MEM_WRITE_ONLY are mutually exclusive.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_READ_ONLY</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the memory object is a |
| readonly memory object when used inside a kernel.</p> |
| <p class="tableblock"> Writing to a buffer or image object created with CL_MEM_READ_ONLY inside |
| a kernel is undefined.</p> |
| <p class="tableblock"> CL_MEM_READ_WRITE or CL_MEM_WRITE_ONLY and CL_MEM_READ_ONLY are mutually |
| exclusive.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_USE_HOST_PTR</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag is valid only if host_ptr is not <code>NULL</code>. |
| If specified, it indicates that the application wants the OpenCL |
| implementation to use memory referenced by host_ptr as the storage bits |
| for the memory object.</p> |
| <p class="tableblock"> The contents of the memory pointed to by host_ptr at the time of the |
| clCreateBuffer call define the initial contents of the buffer object.</p> |
| <p class="tableblock"> OpenCL implementations are allowed to cache the buffer contents pointed |
| to by host_ptr in device memory. |
| This cached copy can be used when kernels are executed on a device.</p> |
| <p class="tableblock"> The result of OpenCL commands that operate on multiple buffer objects |
| created with the same host_ptr or from overlapping host or SVM regions |
| is considered to be undefined.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_ALLOC_HOST_PTR</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the application wants the OpenCL implementation |
| to allocate memory from host accessible memory.</p> |
| <p class="tableblock"> CL_MEM_ALLOC_HOST_PTR and CL_MEM_USE_HOST_PTR are mutually exclusive.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_COPY_HOST_PTR</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag is valid only if host_ptr is not <code>NULL</code>. |
| If specified, it indicates that the application wants the OpenCL |
| implementation to allocate memory for the memory object and copy the |
| data from memory referenced by host_ptr. |
| The implementation will copy the memory immediately and host_ptr is |
| available for reuse by the application when the <strong>clCreateBuffer</strong> or |
| <strong>clCreateImage</strong> operation returns.</p> |
| <p class="tableblock"> CL_MEM_COPY_HOST_PTR and CL_MEM_USE_HOST_PTR are mutually exclusive.</p> |
| <p class="tableblock"> CL_MEM_COPY_HOST_PTR can be used with CL_MEM_ALLOC_HOST_PTR to |
| initialize the contents of the cl_mem object allocated using |
| host-accessible (e.g. PCIe) memory.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_HOST_WRITE_ONLY</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the host will only write to the memory object |
| (using OpenCL APIs that enqueue a write or a map for write). |
| This can be used to optimize write access from the host (e.g. enable |
| write-combined allocations for memory objects for devices that |
| communicate with the host over a system bus such as PCIe).</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_HOST_READ_ONLY</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the host will only read |
| the memory object (using OpenCL APIs that enqueue a read or a map for |
| read).</p> |
| <p class="tableblock"> CL_MEM_HOST_WRITE_ONLY and CL_MEM_HOST_READ_ONLY are mutually exclusive.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_HOST_NO_ACCESS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the host will not read or |
| write the memory object.</p> |
| <p class="tableblock"> CL_MEM_HOST_WRITE_ONLY or CL_MEM_HOST_READ_ONLY and |
| CL_MEM_HOST_NO_ACCESS are mutually exclusive.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p><em>size</em> is the size in bytes of the buffer memory object to be allocated.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>host_ptr</em> is a pointer to the buffer data that may already be allocated by |
| the application. |
| The size of the buffer that <em>host_ptr</em> points to must be ≥ <em>size</em> bytes.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The user is responsible for ensuring that data passed into and out of OpenCL |
| images are natively aligned relative to the start of the buffer as per |
| kernel language or IL requirements. |
| OpenCL buffers created with CL_MEM_USE_HOST_PTR need to provide an |
| appropriately aligned host memory pointer that is aligned to the data types |
| used to access these buffers in a kernel(s).</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>errcode_ret</em> will return an appropriate error code. |
| If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <strong>clCreateBuffer</strong> is called with CL_MEM_USE_HOST_PTR set in its <em>flags</em> |
| argument, the contents of the memory pointed to by <em>host_ptr</em> at the time |
| of the <strong>clCreateBuffer</strong> call define the initial contents of the |
| buffer object.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <strong>clCreateBuffer</strong> is called with a pointer returned by <strong>clSVMAlloc</strong> as its |
| <em>host_ptr</em> argument, and CL_MEM_USE_HOST_PTR is set in its <em>flags</em> argument, |
| <strong>clCreateBuffer</strong> will succeed and return a valid non-zero buffer object as |
| long as the <em>size</em> argument to <strong>clCreateBuffer</strong> is no larger than the <em>size</em> |
| argument passed in the original <strong>clSVMAlloc</strong> call. |
| The new buffer object returned has the shared memory as the underlying |
| storage. |
| Locations in the buffers underlying shared memory can be operated on using |
| atomic operations to the devices level of support as defined in the memory |
| model.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreateBuffer</strong> returns a valid non-zero buffer object and <em>errcode_ret</em> is |
| set to CL_SUCCESS if the buffer object is created successfully. |
| Otherwise, it returns a <code>NULL</code> value with one of the following error values |
| returned in <em>errcode_ret</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if values specified in <em>flags</em> are not valid as defined |
| in the <a href="#memory-flags-table">Memory Flags</a> table.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_BUFFER_SIZE if <em>size</em> is 0<sup>4</sup>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_HOST_PTR if <em>host_ptr</em> is <code>NULL</code> and CL_MEM_USE_HOST_PTR or |
| CL_MEM_COPY_HOST_PTR are set in <em>flags</em> or if <em>host_ptr</em> is not <code>NULL</code> |
| but CL_MEM_COPY_HOST_PTR or CL_MEM_USE_HOST_PTR are not set in <em>flags</em>.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for buffer object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">4</dt> |
| <dd> |
| <p>Implementations may return CL_INVALID_BUFFER_SIZE if size is greater |
| than CL_DEVICE_MAX_MEM_ALLOC_SIZE value specified in the |
| <a href="#device-queries-table">Device Queries</a> table for all devices in |
| context.</p> |
| </dd> |
| </dl> |
| </div> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_mem clCreateSubBuffer(cl_mem buffer, |
| cl_mem_flags flags, |
| cl_buffer_create_type buffer_create_type, |
| <span class="directive">const</span> <span class="directive">void</span> *buffer_create_info, |
| cl_int *errcode_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>can be used to create a new buffer object (referred to as a sub-buffer |
| object) from an existing buffer object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>buffer</em> must be a valid buffer object and cannot be a sub-buffer object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>flags</em> is a bit-field that is used to specify allocation and usage |
| information about the sub-buffer memory object being created and is |
| described in the <a href="#memory-flags-table">Memory Flags</a> table. |
| If the CL_MEM_READ_WRITE, CL_MEM_READ_ONLY or CL_MEM_WRITE_ONLY values are |
| not specified in <em>flags</em>, they are inherited from the corresponding memory |
| access qualifiers associated with <em>buffer</em>. |
| The CL_MEM_USE_HOST_PTR, CL_MEM_ALLOC_HOST_PTR and CL_MEM_COPY_HOST_PTR |
| values cannot be specified in <em>flags</em> but are inherited from the |
| corresponding memory access qualifiers associated with <em>buffer</em>. |
| If CL_MEM_COPY_HOST_PTR is specified in the memory access qualifier values |
| associated with <em>buffer</em> it does not imply any additional copies when the |
| sub-buffer is created from <em>buffer</em>. |
| If the CL_MEM_HOST_WRITE_ONLY, CL_MEM_HOST_READ_ONLY or |
| CL_MEM_HOST_NO_ACCESS values are not specified in <em>flags</em>, they are |
| inherited from the corresponding memory access qualifiers associated with |
| <em>buffer</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>buffer_create_type</em> and <em>buffer_create_info</em> describe the type of buffer |
| object to be created. |
| The list of supported values for <em>buffer_create_type</em> and corresponding |
| descriptor that <em>buffer_create_info</em> points to is described in the |
| <a href="#subbuffer-create-info-table">SubBuffer Attributes</a> table.</p> |
| </div> |
| <table id="subbuffer-create-info-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 12. List of supported names and values in <strong>clCreateSubBuffer</strong></caption> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_buffer_create_type</strong></th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_BUFFER_CREATE_TYPE_REGION</strong></p></td> |
| <td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph"> |
| <p>Create a buffer object that represents a |
| specific region in buffer.</p> |
| </div> |
| <div class="openblock"> |
| <div class="content"> |
| <div class="paragraph"> |
| <p>buffer_create_info is a pointer to the following structure:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c"><span class="keyword">typedef</span> <span class="keyword">struct</span> _cl_buffer_region { |
| size_t origin; |
| size_t size; |
| } cl_buffer_region;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>(<em>origin</em>, <em>size</em>) defines the offset and size in bytes in buffer.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If buffer is created with CL_MEM_USE_HOST_PTR, the host_ptr associated with |
| the buffer object returned is <em>host_ptr + origin</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The buffer object returned references the data store allocated for buffer |
| and points to a specific region given by (origin, size) in this data store.</p> |
| </div> |
| <div class="paragraph"> |
| <p>CL_INVALID_VALUE is returned in errcode_ret if the region specified by |
| (origin, size) is out of bounds in buffer.</p> |
| </div> |
| <div class="paragraph"> |
| <p>CL_INVALID_BUFFER_SIZE if size is 0.</p> |
| </div> |
| <div class="paragraph"> |
| <p>CL_MISALIGNED_SUB_BUFFER_OFFSET is returned in errcode_ret if there are no |
| devices in context associated with buffer for which the origin value is |
| aligned to the CL_DEVICE_MEM_BASE_ADDR_ALIGN value.</p> |
| </div> |
| </div> |
| </div></div></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p><strong>clCreateSubBuffer</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors in <em>errcode_ret</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>buffer</em> is not a valid buffer object or is a |
| sub-buffer object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>buffer</em> was created with CL_MEM_WRITE_ONLY and |
| <em>flags</em> specifies CL_MEM_READ_WRITE or CL_MEM_READ_ONLY, or if <em>buffer</em> |
| was created with CL_MEM_READ_ONLY and <em>flags</em> specifies |
| CL_MEM_READ_WRITE or CL_MEM_WRITE_ONLY, or if <em>flags</em> specifies |
| CL_MEM_USE_HOST_PTR or CL_MEM_ALLOC_HOST_PTR or CL_MEM_COPY_HOST_PTR.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>buffer</em> was created with CL_MEM_HOST_WRITE_ONLY and |
| <em>flags</em> specify CL_MEM_HOST_READ_ONLY, or if <em>buffer</em> was created with |
| CL_MEM_HOST_READ_ONLY and <em>flags</em> specify CL_MEM_HOST_WRITE_ONLY, or if |
| <em>buffer</em> was created with CL_MEM_HOST_NO_ACCESS and <em>flags</em> specify |
| CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_WRITE_ONLY.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if value specified in <em>buffer_create_type</em> is not |
| valid.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if value(s) specified in <em>buffer_create_info</em> (for a |
| given <em>buffer_create_type</em>) is not valid or if <em>buffer_create_info</em> is |
| <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_BUFFER_SIZE if <em>size</em> is 0.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for sub-buffer object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>Concurrent reading from, writing to and copying between both a buffer object |
| and its sub-buffer object(s) is undefined. |
| Concurrent reading from, writing to and copying between overlapping |
| sub-buffer objects created with the same buffer object is undefined. |
| Only reading from both a buffer object and its sub-buffer objects or reading |
| from multiple overlapping sub-buffer objects is defined.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_reading_writing_and_copying_buffer_objects">5.2.2. Reading, Writing and Copying Buffer Objects</h4> |
| <div class="paragraph"> |
| <p>The following functions enqueue commands to read from a buffer object to |
| host memory or write to a buffer object from host memory.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueReadBuffer(cl_command_queue command_queue, |
| cl_mem buffer, |
| cl_bool blocking_read, |
| size_t offset, |
| size_t size, |
| <span class="directive">void</span> *ptr, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueWriteBuffer(cl_command_queue command_queue, |
| cl_mem buffer, |
| cl_bool blocking_write, |
| size_t offset, |
| size_t size, |
| <span class="directive">const</span> <span class="directive">void</span> *ptr, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> is a valid host command-queue in which the read / write |
| command will be queued. |
| <em>command_queue</em> and <em>buffer</em> must be created with the same OpenCL context.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>buffer</em> refers to a valid buffer object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>blocking_read</em> and <em>blocking_write</em> indicate if the read and write |
| operations are <em>blocking</em> or <em>non-blocking</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_read</em> is CL_TRUE i.e. the read command is blocking, |
| <strong>clEnqueueReadBuffer</strong> does not return until the buffer data has been read |
| and copied into memory pointed to by <em>ptr</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_read</em> is CL_FALSE i.e. the read command is non-blocking, |
| <strong>clEnqueueReadBuffer</strong> queues a non-blocking read command and returns. |
| The contents of the buffer that <em>ptr</em> points to cannot be used until the |
| read command has completed. |
| The <em>event</em> argument returns an event object which can be used to query the |
| execution status of the read command. |
| When the read command has completed, the contents of the buffer that <em>ptr</em> |
| points to can be used by the application.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_write</em> is CL_TRUE, the write command is blocking and does not |
| return until the command is complete, including transfer of the data. |
| The memory pointed to by <em>ptr</em> can be reused by the application after the |
| <strong>clEnqueueWriteBuffer</strong> call returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_write</em> is CL_FALSE, the OpenCL implementation will use <em>ptr</em> to |
| perform a non-blocking write. |
| As the write is non-blocking the implementation can return immediately. |
| The memory pointed to by <em>ptr</em> cannot be reused by the application after the |
| call returns. |
| The <em>event</em> argument returns an event object which can be used to query the |
| execution status of the write command. |
| When the write command has completed, the memory pointed to by <em>ptr</em> can |
| then be reused by the application.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>offset</em> is the offset in bytes in the buffer object to read from or write |
| to.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>size</em> is the size in bytes of data being read or written.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>ptr</em> is the pointer to buffer in host memory where data is to be read into |
| or to be written from.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait |
| on any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular read / write |
| command and can be used to query or queue a wait for this particular command |
| to complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueReadBuffer</strong> and <strong>clEnqueueWriteBuffer</strong> return CL_SUCCESS if the |
| function is executed successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em> and |
| <em>buffer</em> are not the same or if the context associated with |
| <em>command_queue</em> and events in <em>event_wait_list</em> are not the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>buffer</em> is not a valid buffer object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if the region being read or written specified by |
| (<em>offset</em>, <em>size</em>) is out of bounds or if <em>ptr</em> is a <code>NULL</code> value.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>buffer</em> is a sub-buffer object and |
| <em>offset</em> specified when the sub-buffer object is created is not aligned |
| to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated with |
| <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the read and write |
| operations are blocking and the execution status of any of the events in |
| <em>event_wait_list</em> is a negative integer value.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for data store associated with <em>buffer</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if <strong>clEnqueueReadBuffer</strong> is called on <em>buffer</em> |
| which has been created with CL_MEM_HOST_WRITE_ONLY or |
| CL_MEM_HOST_NO_ACCESS.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if <strong>clEnqueueWriteBuffer</strong> is called on <em>buffer</em> |
| which has been created with CL_MEM_HOST_READ_ONLY or |
| CL_MEM_HOST_NO_ACCESS.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The following functions enqueue commands to read a 2D or 3D rectangular |
| region from a buffer object to host memory or write a 2D or 3D rectangular |
| region to a buffer object from host memory.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueReadBufferRect(cl_command_queue command_queue, |
| cl_mem buffer, |
| cl_bool blocking_read, |
| <span class="directive">const</span> size_t *buffer_origin, |
| <span class="directive">const</span> size_t *host_origin, |
| <span class="directive">const</span> size_t *region, |
| size_t buffer_row_pitch, |
| size_t buffer_slice_pitch, |
| size_t host_row_pitch, |
| size_t host_slice_pitch, |
| <span class="directive">void</span> *ptr, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueWriteBufferRect(cl_command_queue command_queue, |
| cl_mem buffer, |
| cl_bool blocking_write, |
| <span class="directive">const</span> size_t *buffer_origin, |
| <span class="directive">const</span> size_t *host_origin, |
| <span class="directive">const</span> size_t *region, |
| size_t buffer_row_pitch, |
| size_t buffer_slice_pitch, |
| size_t host_row_pitch, |
| size_t host_slice_pitch, |
| <span class="directive">const</span> <span class="directive">void</span> *ptr, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> refers is a valid host command-queue in which the read / |
| write command will be queued. |
| <em>command_queue</em> and <em>buffer</em> must be created with the same OpenCL context.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>buffer</em> refers to a valid buffer object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>blocking_read</em> and <em>blocking_write</em> indicate if the read and write |
| operations are <em>blocking</em> or <em>non-blocking</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_read</em> is CL_TRUE i.e. the read command is blocking, |
| <strong>clEnqueueReadBufferRect</strong> does not return until the buffer data has been |
| read and copied into memory pointed to by <em>ptr</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_read</em> is CL_FALSE i.e. the read command is non-blocking, |
| <strong>clEnqueueReadBufferRect</strong> queues a non-blocking read command and returns. |
| The contents of the buffer that <em>ptr</em> points to cannot be used until the |
| read command has completed. |
| The <em>event</em> argument returns an event object which can be used to query the |
| execution status of the read command. |
| When the read command has completed, the contents of the buffer that <em>ptr</em> |
| points to can be used by the application.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_write</em> is CL_TRUE, the write command is blocking and does not |
| return until the command is complete, including transfer of the data. |
| The memory pointed to by <em>ptr</em> can be reused by the application after the |
| <strong>clEnqueueWriteBufferRect</strong> call returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_write</em> is CL_FALSE, the OpenCL implementation will use <em>ptr</em> to |
| perform a non-blocking write. |
| As the write is non-blocking the implementation can return immediately. |
| The memory pointed to by <em>ptr</em> cannot be reused by the application after the |
| call returns. |
| The <em>event</em> argument returns an event object which can be used to query the |
| execution status of the write command. |
| When the write command has completed, the memory pointed to by <em>ptr</em> can |
| then be reused by the application.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>buffer_origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in the memory region |
| associated with <em>buffer</em>. |
| For a 2D rectangle region, the <em>z</em> value given by <em>buffer_origin</em>[2] should |
| be 0. |
| The offset in bytes is computed as <em>buffer_origin</em>[2] × |
| <em>buffer_slice_pitch</em> + <em>buffer_origin</em>[1] × <em>buffer_row_pitch</em> + |
| <em>buffer_origin</em>[0].</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>host_origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in the memory region |
| pointed to by <em>ptr</em>. |
| For a 2D rectangle region, the <em>z</em> value given by <em>host_origin</em>[2] should be |
| 0. |
| The offset in bytes is computed as <em>host_origin</em>[2] × |
| <em>host_slice_pitch</em> + <em>host_origin</em>[1] × <em>host_row_pitch</em> + |
| <em>host_origin</em>[0].</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>region</em> defines the (<em>width</em> in bytes, <em>height</em> in rows, <em>depth</em> in slices) |
| of the 2D or 3D rectangle being read or written. |
| For a 2D rectangle copy, the <em>depth</em> value given by <em>region</em>[2] should be 1. |
| The values in region cannot be 0.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>buffer_row_pitch</em> is the length of each row in bytes to be used for the |
| memory region associated with <em>buffer</em>. |
| If <em>buffer_row_pitch</em> is 0, <em>buffer_row_pitch</em> is computed as <em>region</em>[0].</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>buffer_slice_pitch</em> is the length of each 2D slice in bytes to be used for |
| the memory region associated with <em>buffer</em>. |
| If <em>buffer_slice_pitch</em> is 0, <em>buffer_slice_pitch</em> is computed as |
| <em>region</em>[1] × <em>buffer_row_pitch</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>host_row_pitch</em> is the length of each row in bytes to be used for the |
| memory region pointed to by <em>ptr</em>. |
| If <em>host_row_pitch</em> is 0, <em>host_row_pitch</em> is computed as <em>region</em>[0].</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>host_slice_pitch</em> is the length of each 2D slice in bytes to be used for |
| the memory region pointed to by <em>ptr</em>. |
| If <em>host_slice_pitch</em> is 0, <em>host_slice_pitch</em> is computed as <em>region</em>[1] |
| × <em>host_row_pitch</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>ptr</em> is the pointer to buffer in host memory where data is to be read into |
| or to be written from.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait |
| on any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular read / write |
| command and can be used to query or queue a wait for this particular command |
| to complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueReadBufferRect</strong> and <strong>clEnqueueWriteBufferRect</strong> return CL_SUCCESS |
| if the function is executed successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em> and |
| <em>buffer</em> are not the same or if the context associated with |
| <em>command_queue</em> and events in <em>event_wait_list</em> are not the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>buffer</em> is not a valid buffer object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if the region being read or written specified by |
| (<em>buffer_origin</em>, <em>region</em>, <em>buffer_row_pitch</em>, <em>buffer_slice_pitch</em>) is |
| out of bounds.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>ptr</em> is a <code>NULL</code> value.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if any <em>region</em> array element is 0.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>buffer_row_pitch</em> is not 0 and is less than |
| <em>region</em>[0].</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>host_row_pitch</em> is not 0 and is less than |
| <em>region</em>[0].</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>buffer_slice_pitch</em> is not 0 and is less than |
| <em>region</em>[1] × <em>buffer_row_pitch</em> and not a multiple of |
| <em>buffer_row_pitch</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>host_slice_pitch</em> is not 0 and is less than |
| <em>region</em>[1] × <em>host_row_pitch</em> and not a multiple of |
| <em>host_row_pitch</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>buffer</em> is a sub-buffer object and |
| <em>offset</em> specified when the sub-buffer object is created is not aligned |
| to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated with |
| <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the read and write |
| operations are blocking and the execution status of any of the events in |
| <em>event_wait_list</em> is a negative integer value.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for data store associated with <em>buffer</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if <strong>clEnqueueReadBufferRect</strong> is called on <em>buffer</em> |
| which has been created with CL_MEM_HOST_WRITE_ONLY or |
| CL_MEM_HOST_NO_ACCESS.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if <strong>clEnqueueWriteBufferRect</strong> is called on <em>buffer</em> |
| which has been created with CL_MEM_HOST_READ_ONLY or |
| CL_MEM_HOST_NO_ACCESS.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>Calling <strong>clEnqueueReadBuffer</strong> to read a region of the buffer object with the |
| <em>ptr</em> argument value set to <em>host_ptr</em> + <em>offset</em>, where <em>host_ptr</em> is a |
| pointer to the memory region specified when the buffer object being read is |
| created with CL_MEM_USE_HOST_PTR, must meet the following requirements in |
| order to avoid undefined behavior:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>All commands that use this buffer object or a memory object (buffer or |
| image) created from this buffer object have finished execution before |
| the read command begins execution.</p> |
| </li> |
| <li> |
| <p>The buffer object or memory objects created from this buffer object are |
| not mapped.</p> |
| </li> |
| <li> |
| <p>The buffer object or memory objects created from this buffer object are |
| not used by any command-queue until the read command has finished |
| execution.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Calling <strong>clEnqueueReadBufferRect</strong> to read a region of the buffer object with |
| the <em>ptr</em> argument value set to <em>host_ptr</em> and <em>host_origin</em>, |
| <em>buffer_origin</em> values are the same, where <em>host_ptr</em> is a pointer to the |
| memory region specified when the buffer object being read is created with |
| CL_MEM_USE_HOST_PTR, must meet the same requirements given above for |
| <strong>clEnqueueReadBuffer</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Calling <strong>clEnqueueWriteBuffer</strong> to update the latest bits in a region of the |
| buffer object with the <em>ptr</em> argument value set to <em>host_ptr</em> + <em>offset</em>, |
| where <em>host_ptr</em> is a pointer to the memory region specified when the buffer |
| object being written is created with CL_MEM_USE_HOST_PTR, must meet the |
| following requirements in order to avoid undefined behavior:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>The host memory region given by (<em>host_ptr</em> + <em>offset</em>, <em>cb</em>) contains |
| the latest bits when the enqueued write command begins execution.</p> |
| </li> |
| <li> |
| <p>The buffer object or memory objects created from this buffer object are |
| not mapped.</p> |
| </li> |
| <li> |
| <p>The buffer object or memory objects created from this buffer object are |
| not used by any command-queue until the write command has finished |
| execution.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Calling <strong>clEnqueueWriteBufferRect</strong> to update the latest bits in a region of |
| the buffer object with the <em>ptr</em> argument value set to <em>host_ptr</em> and |
| <em>host_origin</em>, <em>buffer_origin</em> values are the same, where <em>host_ptr</em> is a |
| pointer to the memory region specified when the buffer object being written |
| is created with CL_MEM_USE_HOST_PTR, must meet the following requirements in |
| order to avoid undefined behavior:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>The host memory region given by (<em>buffer_origin region</em>) contains the |
| latest bits when the enqueued write command begins execution.</p> |
| </li> |
| <li> |
| <p>The buffer object or memory objects created from this buffer object are |
| not mapped.</p> |
| </li> |
| <li> |
| <p>The buffer object or memory objects created from this buffer object are |
| not used by any command-queue until the write command has finished |
| execution.</p> |
| </li> |
| </ul> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueCopyBuffer(cl_command_queue command_queue, |
| cl_mem src_buffer, |
| cl_mem dst_buffer, |
| size_t src_offset, |
| size_t dst_offset, |
| size_t size, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a command to copy a buffer object identified by <em>src_buffer</em> to |
| another buffer object identified by <em>dst_buffer</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> refers to a host command-queue in which the copy command |
| will be queued. |
| The OpenCL context associated with <em>command_queue</em>, <em>src_buffer</em> and |
| <em>dst_buffer</em> must be the same.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>src_offset</em> refers to the offset where to begin copying data from |
| <em>src_buffer</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>dst_offset</em> refers to the offset where to begin copying data into |
| <em>dst_buffer</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>size</em> refers to the size in bytes to copy.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait |
| on any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular copy command |
| and can be used to query or queue a wait for this particular command to |
| complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| <strong>clEnqueueBarrierWithWaitList</strong> can be used instead. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueCopyBuffer</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em>, |
| <em>src_buffer</em> and <em>dst_buffer</em> are not the same or if the context |
| associated with <em>command_queue</em> and events in <em>event_wait_list</em> are not |
| the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>src_buffer</em> and <em>dst_buffer</em> are not valid |
| buffer objects.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>src_offset</em>, <em>dst_offset</em>, <em>size</em>, <em>src_offset</em> |
| + <em>size</em> or <em>dst_offset</em> + <em>size</em> require accessing elements |
| outside the <em>src_buffer</em> and <em>dst_buffer</em> buffer objects respectively.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>src_buffer</em> is a sub-buffer object |
| and <em>offset</em> specified when the sub-buffer object is created is not |
| aligned to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated |
| with <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>dst_buffer</em> is a sub-buffer object |
| and <em>offset</em> specified when the sub-buffer object is created is not |
| aligned to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated |
| with <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_MEM_COPY_OVERLAP if <em>src_buffer</em> and <em>dst_buffer</em> are the same buffer |
| or sub-buffer object and the source and destination regions overlap or |
| if <em>src_buffer</em> and <em>dst_buffer</em> are different sub-buffers of the same |
| associated buffer object and they overlap. |
| The regions overlap if <em>src_offset</em> ≤ <em>dst_offset</em> ≤ |
| <em>src_offset</em> + <em>size</em> 1 or if <em>dst_offset</em> ≤ <em>src_offset</em> ≤ |
| <em>dst_offset</em> + <em>size</em> 1.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for data store associated with <em>src_buffer</em> or <em>dst_buffer</em>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueCopyBufferRect(cl_command_queue command_queue, |
| cl_mem src_buffer, |
| cl_mem dst_buffer, |
| <span class="directive">const</span> size_t *src_origin, |
| <span class="directive">const</span> size_t *dst_origin, |
| <span class="directive">const</span> size_t *region, |
| size_t src_row_pitch, |
| size_t src_slice_pitch, |
| size_t dst_row_pitch, |
| size_t dst_slice_pitch, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a command to copy a 2D or 3D rectangular region from the buffer |
| object identified by <em>src_buffer</em> to a 2D or 3D region in the buffer object |
| identified by <em>dst_buffer</em>. |
| Copying begins at the source offset and destination offset which are |
| computed as described below in the description for <em>src_origin</em> and |
| <em>dst_origin</em>. |
| Each byte of the region’s width is copied from the source offset to the |
| destination offset. |
| After copying each width, the source and destination offsets are incremented |
| by their respective source and destination row pitches. |
| After copying each 2D rectangle, the source and destination offsets are |
| incremented by their respective source and destination slice pitches.</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="paragraph"> |
| <p>If <em>src_buffer</em> and <em>dst_buffer</em> are the same buffer object, <em>src_row_pitch</em> |
| must equal <em>dst_row_pitch</em> and <em>src_slice_pitch</em> must equal |
| <em>dst_slice_pitch</em>.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> refers to the host command-queue in which the copy command |
| will be queued. |
| The OpenCL context associated with <em>command_queue</em>, <em>src_buffer</em> and |
| <em>dst_buffer</em> must be the same.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>src_origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in the memory region |
| associated with <em>src_buffer</em>. |
| For a 2D rectangle region, the <em>z</em> value given by <em>src_origin</em>[2] should be |
| 0. |
| The offset in bytes is computed as <em>src_origin</em>[2] × <em>src_slice_pitch</em> |
| + <em>src_origin</em>[1] × <em>src_row_pitch</em> + <em>src_origin</em>[0].</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>dst_origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in the memory region |
| associated with <em>dst_buffer</em>. |
| For a 2D rectangle region, the <em>z</em> value given by <em>dst_origin</em>[2] should be |
| 0. |
| The offset in bytes is computed as <em>dst_origin</em>[2] × <em>dst_slice_pitch</em> |
| + <em>dst_origin</em>[1] × <em>dst_row_pitch</em> + <em>dst_origin</em>[0].</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>region</em> defines the (<em>width</em> in bytes, <em>height</em> in rows, <em>depth</em> in slices) |
| of the 2D or 3D rectangle being copied. |
| For a 2D rectangle, the <em>depth</em> value given by <em>region</em>[2] should be 1. |
| The values in region cannot be 0.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>src_row_pitch</em> is the length of each row in bytes to be used for the memory |
| region associated with <em>src_buffer</em>. |
| If <em>src_row_pitch</em> is 0, <em>src_row_pitch</em> is computed as <em>region</em>[0].</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>src_slice_pitch</em> is the length of each 2D slice in bytes to be used for the |
| memory region associated with <em>src_buffer</em>. |
| If <em>src_slice_pitch</em> is 0, <em>src_slice_pitch</em> is computed as <em>region</em>[1] |
| × <em>src_row_pitch</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>dst_row_pitch</em> is the length of each row in bytes to be used for the memory |
| region associated with <em>dst_buffer</em>. |
| If <em>dst_row_pitch</em> is 0, <em>dst_row_pitch</em> is computed as <em>region</em>[0].</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>dst_slice_pitch</em> is the length of each 2D slice in bytes to be used for the |
| memory region associated with <em>dst_buffer</em>. |
| If <em>dst_slice_pitch</em> is 0, <em>dst_slice_pitch</em> is computed as <em>region</em>[1] |
| × <em>dst_row_pitch</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait |
| on any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular copy command |
| and can be used to query or queue a wait for this particular command to |
| complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| <strong>clEnqueueBarrierWithWaitList</strong> can be used instead. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueCopyBufferRect</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em>, |
| <em>src_buffer</em> and <em>dst_buffer</em> are not the same or if the context |
| associated with <em>command_queue</em> and events in <em>event_wait_list</em> are not |
| the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>src_buffer</em> and <em>dst_buffer</em> are not valid |
| buffer objects.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if (<em>src_origin, region, src_row_pitch, |
| src_slice_pitch</em>) or (<em>dst_origin, region, dst_row_pitch, |
| dst_slice_pitch</em>) require accessing elements outside the <em>src_buffer</em> |
| and <em>dst_buffer</em> buffer objects respectively.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if any <em>region</em> array element is 0.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>src_row_pitch</em> is not 0 and is less than |
| <em>region</em>[0].</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>dst_row_pitch</em> is not 0 and is less than |
| <em>region</em>[0].</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>src_slice_pitch</em> is not 0 and is less than |
| <em>region</em>[1] × <em>src_row_pitch</em> or if <em>src_slice_pitch</em> is not 0 and |
| is not a multiple of <em>src_row_pitch</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>dst_slice_pitch</em> is not 0 and is less than |
| <em>region</em>[1] × <em>dst_row_pitch</em> or if <em>dst_slice_pitch</em> is not 0 and |
| is not a multiple of <em>dst_row_pitch</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>src_buffer</em> and <em>dst_buffer</em> are the same buffer |
| object and <em>src_slice_pitch</em> is not equal to <em>dst_slice_pitch</em> and |
| <em>src_row_pitch</em> is not equal to <em>dst_row_pitch</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_MEM_COPY_OVERLAP if <em>src_buffer</em> and <em>dst_buffer</em> are the same buffer |
| or sub-buffer object and the source and destination regions overlap or |
| if <em>src_buffer</em> and <em>dst_buffer</em> are different sub-buffers of the same |
| associated buffer object and they overlap. |
| Refer to <a href="#check-copy-overlap">CL_MEM_COPY_OVERLAP</a> for details on how |
| to determine if source and destination regions overlap.</p> |
| </li> |
| <li> |
| <p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>src_buffer</em> is a sub-buffer object |
| and <em>offset</em> specified when the sub-buffer object is created is not |
| aligned to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated |
| with <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>dst_buffer</em> is a sub-buffer object |
| and <em>offset</em> specified when the sub-buffer object is created is not |
| aligned to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated |
| with <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for data store associated with <em>src_buffer</em> or <em>dst_buffer</em>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_filling_buffer_objects">5.2.3. Filling Buffer Objects</h4> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueFillBuffer(cl_command_queue command_queue, |
| cl_mem buffer, |
| <span class="directive">const</span> <span class="directive">void</span> *pattern, |
| size_t pattern_size, |
| size_t offset, |
| size_t size, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a command to fill a buffer object with a pattern of a given pattern |
| size. |
| The usage information which indicates whether the memory object can be read |
| or written by a kernel and/or the host and is given by the cl_mem_flags |
| argument value specified when <em>buffer</em> is created is ignored by |
| <strong>clEnqueueFillBuffer</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> refers to the host command-queue in which the fill command |
| will be queued. |
| The OpenCL context associated with <em>command_queue</em> and <em>buffer</em> must be the |
| same.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>buffer</em> is a valid buffer object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>pattern</em> is a pointer to the data pattern of size <em>pattern_size</em> in bytes. |
| <em>pattern</em> will be used to fill a region in <em>buffer</em> starting at <em>offset</em> and |
| is <em>size</em> bytes in size. |
| The data pattern must be a scalar or vector integer or floating-point data |
| type supported by OpenCL as described in <a href="#scalar-data-types">Shared |
| Application Scalar Data Types</a> and <a href="#vector-data-types">Supported |
| Application Vector Data Types</a>. |
| For example, if <em>buffer</em> is to be filled with a pattern of <code>float4</code> values, |
| then <em>pattern</em> will be a pointer to a <code>cl_float4</code> value and <em>pattern_size</em> |
| will be <code>sizeof(cl_float4)</code>. |
| The maximum value of <em>pattern_size</em> is the size of the largest integer or |
| floating-point vector data type supported by the OpenCL device. |
| The memory associated with <em>pattern</em> can be reused or freed after the |
| function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>offset</em> is the location in bytes of the region being filled in <em>buffer</em> and |
| must be a multiple of <em>pattern_size</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>size</em> is the size in bytes of region being filled in <em>buffer</em> and must be a |
| multiple of <em>pattern_size</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait |
| on any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular command and |
| can be used to query or queue a wait for this particular command to |
| complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| <strong>clEnqueueBarrierWithWaitList</strong> can be used instead. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueFillBuffer</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em> and |
| <em>buffer</em> are not the same or if the context associated with |
| <em>command_queue</em> and events in <em>event_wait_list</em> are not the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>buffer</em> is not a valid buffer object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>offset</em> or <em>offset</em> + <em>size</em> require accessing |
| elements outside the <em>buffer</em> buffer object respectively.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>pattern</em> is <code>NULL</code> or if <em>pattern_size</em> is 0 or if |
| <em>pattern_size</em> is not one of { 1, 2, 4, 8, 16, 32, 64, 128 }.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>offset</em> and <em>size</em> are not a multiple of |
| <em>pattern_size</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>buffer</em> is a sub-buffer object and |
| offset specified when the sub-buffer object is created is not aligned to |
| CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated with <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for data store associated with <em>buffer</em>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_mapping_buffer_objects">5.2.4. Mapping Buffer Objects</h4> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c"><span class="directive">void</span>* clEnqueueMapBuffer(cl_command_queue command_queue, |
| cl_mem buffer, |
| cl_bool blocking_map, |
| cl_map_flags map_flags, |
| size_t offset, |
| size_t size, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event, |
| cl_int *errcode_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a command to map a region of the buffer object given by <em>buffer</em> |
| into the host address space and returns a pointer to this mapped region.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> must be a valid host command-queue.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>blocking_map</em> indicates if the map operation is <em>blocking</em> or |
| <em>non-blocking</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_map</em> is CL_TRUE, <strong>clEnqueueMapBuffer</strong> does not return until the |
| specified region in <em>buffer</em> is mapped into the host address space and the |
| application can access the contents of the mapped region using the pointer |
| returned by <strong>clEnqueueMapBuffer</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_map</em> is CL_FALSE i.e. map operation is non-blocking, the |
| pointer to the mapped region returned by <strong>clEnqueueMapBuffer</strong> cannot be used |
| until the map command has completed. |
| The <em>event</em> argument returns an event object which can be used to query the |
| execution status of the map command. |
| When the map command is completed, the application can access the contents |
| of the mapped region using the pointer returned by <strong>clEnqueueMapBuffer</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>map_flags</em> is a bit-field and is described in the |
| <a href="#memory-map-flags-table">Memory Map Flags</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>buffer</em> is a valid buffer object. |
| The OpenCL context associated with <em>command_queue</em> and <em>buffer</em> must be the |
| same.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>offset</em> and <em>size</em> are the offset in bytes and the size of the region in |
| the buffer object that is being mapped.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait |
| on any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular command and |
| can be used to query or queue a wait for this particular command to |
| complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>errcode_ret</em> will return an appropriate error code. |
| If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueMapBuffer</strong> will return a pointer to the mapped region. |
| The <em>errcode_ret</em> is set to CL_SUCCESS.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A <code>NULL</code> pointer is returned otherwise with one of the following error |
| values returned in <em>errcode_ret</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and |
| <em>buffer</em> are not the same or if the context associated with |
| <em>command_queue</em> and events in <em>event_wait_list</em> are not the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>buffer</em> is not a valid buffer object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if region being mapped given by (<em>offset</em>, <em>size</em>) is |
| out of bounds or if <em>size</em> is 0 or if values specified in <em>map_flags</em> |
| are not valid.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>buffer</em> is a sub-buffer object and |
| <em>offset</em> specified when the sub-buffer object is created is not aligned |
| to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for the device associated with |
| <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_MAP_FAILURE if there is a failure to map the requested region into |
| the host address space. |
| This error cannot occur for buffer objects created with |
| CL_MEM_USE_HOST_PTR or CL_MEM_ALLOC_HOST_PTR.</p> |
| </li> |
| <li> |
| <p>CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the map operation is |
| blocking and the execution status of any of the events in |
| <em>event_wait_list</em> is a negative integer value.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for data store associated with <em>buffer</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if buffer_ has been created with |
| CL_MEM_HOST_WRITE_ONLY or CL_MEM_HOST_NO_ACCESS and CL_MAP_READ is set |
| in <em>map_flags</em> or if <em>buffer</em> has been created with |
| CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_NO_ACCESS and CL_MAP_WRITE or |
| CL_MAP_WRITE_INVALIDATE_REGION is set in <em>map_flags</em>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if mapping would lead to overlapping regions being |
| mapped for writing.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The pointer returned maps a region starting at <em>offset</em> and is at least |
| <em>size</em> bytes in size. |
| The result of a memory access outside this region is undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the buffer object is created with CL_MEM_USE_HOST_PTR set in <em>mem_flags</em>, |
| the following will be true:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>The <em>host_ptr</em> specified in <strong>clCreateBuffer</strong> to contain the latest bits |
| in the region being mapped when the <strong>clEnqueueMapBuffer</strong> command has |
| completed.</p> |
| </li> |
| <li> |
| <p>The pointer value returned by <strong>clEnqueueMapBuffer</strong> will be derived from |
| the <em>host_ptr</em> specified when the buffer object is created.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Mapped buffer objects are unmapped using <strong>clEnqueueUnmapMemObject</strong>. |
| This is described in <a href="#unmapping-mapped-memory">Unmapping Mapped Memory |
| Objects</a>.</p> |
| </div> |
| <table id="memory-map-flags-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 13. List of supported cl_map_flags values</caption> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_map_flags</strong></th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MAP_READ</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the region being mapped in the memory object is |
| being mapped for reading.</p> |
| <p class="tableblock"> The pointer returned by <strong>clEnqueueMapBuffer</strong> (<strong>clEnqueueMapImage</strong>) is |
| guaranteed to contain the latest bits in the region being mapped when |
| the <strong>clEnqueueMapBuffer</strong> (<strong>clEnqueueMapImage</strong>) command has completed.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MAP_WRITE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the region being mapped in the memory object is |
| being mapped for writing.</p> |
| <p class="tableblock"> The pointer returned by <strong>clEnqueueMapBuffer</strong> (<strong>clEnqueueMapImage</strong>) is |
| guaranteed to contain the latest bits in the region being mapped when |
| the <strong>clEnqueueMapBuffer</strong> (<strong>clEnqueueMapImage</strong>) command has completed</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MAP_WRITE_INVALIDATE_REGION</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the region being mapped in the memory object is |
| being mapped for writing.</p> |
| <p class="tableblock"> The contents of the region being mapped are to be discarded. |
| This is typically the case when the region being mapped is overwritten |
| by the host. |
| This flag allows the implementation to no longer guarantee that the |
| pointer returned by <strong>clEnqueueMapBuffer</strong> (<strong>clEnqueueMapImage</strong>) contains |
| the latest bits in the region being mapped which can be a significant |
| performance enhancement.</p> |
| <p class="tableblock"> CL_MAP_READ or CL_MAP_WRITE and CL_MAP_WRITE_INVALIDATE_REGION are |
| mutually exclusive.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_image_objects">5.3. Image Objects</h3> |
| <div class="paragraph"> |
| <p>An <em>image</em> object is used to store a one-, two- or three-dimensional |
| texture, frame-buffer or image. |
| The elements of an image object are selected from a list of predefined image |
| formats. |
| The minimum number of elements in a memory object is one.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="_creating_image_objects">5.3.1. Creating Image Objects</h4> |
| <div class="paragraph"> |
| <p>A <strong>1D image</strong>, <strong>1D image buffer</strong>, <strong>1D image array</strong>, <strong>2D image</strong>, <strong>2D image |
| array</strong> and <strong>3D image object</strong> can be created using the following function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_mem clCreateImage(cl_context context, |
| cl_mem_flags flags, |
| <span class="directive">const</span> cl_image_format *image_format, |
| <span class="directive">const</span> cl_image_desc *image_desc, |
| <span class="directive">void</span> *host_ptr, |
| cl_int *errcode_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><em>context</em> is a valid OpenCL context on which the image object is to be |
| created.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>flags</em> is a bit-field that is used to specify allocation and usage |
| information about the image memory object being created and is described in |
| the <a href="#memory-flags-table">Memory Flags</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For all image types except CL_MEM_OBJECT_IMAGE1D_BUFFER, if value specified |
| for <em>flags</em> is 0, the default is used which is CL_MEM_READ_WRITE.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For CL_MEM_OBJECT_IMAGE1D_BUFFER image type, or an image created from |
| another memory object (image or buffer), if the CL_MEM_READ_WRITE, |
| CL_MEM_READ_ONLY or CL_MEM_WRITE_ONLY values are not specified in <em>flags</em>, |
| they are inherited from the corresponding memory access qualifiers associated |
| with <em>mem_object</em>. |
| The CL_MEM_USE_HOST_PTR, CL_MEM_ALLOC_HOST_PTR and CL_MEM_COPY_HOST_PTR |
| values cannot be specified in <em>flags</em> but are inherited from the |
| corresponding memory access qualifiers associated with <em>mem_object</em>. |
| If CL_MEM_COPY_HOST_PTR is specified in the memory access qualifier values |
| associated with <em>mem_object</em> it does not imply any additional copies when |
| the image is created from <em>mem_object</em>. |
| If the CL_MEM_HOST_WRITE_ONLY, CL_MEM_HOST_READ_ONLY or |
| CL_MEM_HOST_NO_ACCESS values are not specified in <em>flags</em>, they are |
| inherited from the corresponding memory access qualifiers associated with |
| <em>mem_object</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>image_format</em> is a pointer to a structure that describes format properties |
| of the image to be allocated. |
| A 1D image buffer or 2D image can be created from a buffer by specifying a |
| buffer object in the <em>image_desc→mem_object</em>. |
| A 2D image can be created from another 2D image object by specifying an |
| image object in the <em>image_desc</em>→_mem_object_. |
| Refer to <a href="#image-format-descriptor">Image Format Descriptor</a> for a detailed |
| description of the image format descriptor.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>image_desc</em> is a pointer to a structure that describes type and dimensions |
| of the image to be allocated. |
| Refer to <a href="#image-descriptor">Image Descriptor</a> for a detailed description |
| of the image descriptor.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>host_ptr</em> is a pointer to the image data that may already be allocated by |
| the application. |
| It is only used to initialize the image, and can be freed after the call to |
| <strong>clCreateImage</strong>. |
| Refer to table below for a description of how large the buffer that |
| <em>host_ptr</em> points to must be.</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">Image Type</th> |
| <th class="tableblock halign-left valign-top">Size of buffer that <em>host_ptr</em> points to</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_OBJECT_IMAGE1D</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">≥ image_row_pitch</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_OBJECT_IMAGE1D_BUFFER</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">≥ image_row_pitch</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_OBJECT_IMAGE2D</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">≥ image_row_pitch × image_height</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_OBJECT_IMAGE3D</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">≥ image_slice_pitch × image_depth</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_OBJECT_IMAGE1D_ARRAY</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">≥ image_slice_pitch × image_array_size</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_OBJECT_IMAGE2D_ARRAY</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">≥ image_slice_pitch × image_array_size</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>For a 3D image or 2D image array, the image data specified by <em>host_ptr</em> is |
| stored as a linear sequence of adjacent 2D image slices or 2D images |
| respectively. |
| Each 2D image is a linear sequence of adjacent scanlines. |
| Each scanline is a linear sequence of image elements.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For a 2D image, the image data specified by <em>host_ptr</em> is stored as a linear |
| sequence of adjacent scanlines. |
| Each scanline is a linear sequence of image elements.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For a 1D image array, the image data specified by <em>host_ptr</em> is stored as a |
| linear sequence of adjacent 1D images. |
| Each 1D image is stored as a single scanline which is a linear sequence of |
| adjacent elements.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For 1D image or 1D image buffer, the image data specified by <em>host_ptr</em> is |
| stored as a single scanline which is a linear sequence of adjacent elements.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Image elements are stored according to their image format as described in |
| <a href="#image-format-descriptor">Image Format Descriptor</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>errcode_ret</em> will return an appropriate error code. |
| If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreateImage</strong> returns a valid non-zero image object created and the |
| <em>errcode_ret</em> is set to CL_SUCCESS if the image object is created |
| successfully. |
| Otherwise, it returns a <code>NULL</code> value with one of the following error values |
| returned in <em>errcode_ret</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if values specified in <em>flags</em> are not valid.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if values specified in <em>image_format</em> |
| are not valid or if <em>image_format</em> is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if a 2D image is created from a |
| buffer and the row pitch and base address alignment does not follow the |
| rules described for creating a 2D image from a buffer.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if a 2D image is created from a 2D |
| image object and the rules described above are not followed.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_IMAGE_DESCRIPTOR if values specified in <em>image_desc</em> are not |
| valid or if <em>image_desc</em> is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_IMAGE_SIZE if image dimensions specified in <em>image_desc</em> |
| exceed the maximum image dimensions described in the |
| <a href="#device-queries-table">Device Queries</a> table for all devices |
| in_context_.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_HOST_PTR if <em>host_ptr</em> is <code>NULL</code> and CL_MEM_USE_HOST_PTR or |
| CL_MEM_COPY_HOST_PTR are set in <em>flags</em> or if <em>host_ptr</em> is not <code>NULL</code> |
| but CL_MEM_COPY_HOST_PTR or CL_MEM_USE_HOST_PTR are not set in <em>flags</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if an image is being created from another memory object |
| (buffer or image) under one of the following circumstances: 1) |
| <em>mem_object</em> was created with CL_MEM_WRITE_ONLY and <em>flags</em> specifies |
| CL_MEM_READ_WRITE or CL_MEM_READ_ONLY, 2) <em>mem_object</em> was created with |
| CL_MEM_READ_ONLY and <em>flags</em> specifies CL_MEM_READ_WRITE or |
| CL_MEM_WRITE_ONLY, 3) <em>flags</em> specifies CL_MEM_USE_HOST_PTR or |
| CL_MEM_ALLOC_HOST_PTR or CL_MEM_COPY_HOST_PTR.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if an image is being created from another memory object |
| (buffer or image) and <em>mem_object</em> object was created with |
| CL_MEM_HOST_WRITE_ONLY and <em>flags</em> specifies CL_MEM_HOST_READ_ONLY, or |
| if <em>mem_object</em> was created with CL_MEM_HOST_READ_ONLY and <em>flags</em> |
| specifies CL_MEM_HOST_WRITE_ONLY, or if <em>mem_object</em> was created with |
| CL_MEM_HOST_NO_ACCESS and_flags_ specifies CL_MEM_HOST_READ_ONLY or |
| CL_MEM_HOST_WRITE_ONLY.</p> |
| </li> |
| <li> |
| <p>CL_IMAGE_FORMAT_NOT_SUPPORTED if the <em>image_format</em> is not supported.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for image object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if there are no devices in <em>context</em> that support |
| images (i.e. CL_DEVICE_IMAGE_SUPPORT specified in the |
| <a href="#device-queries-table">Device Queries</a> table is CL_FALSE).</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="sect4"> |
| <h5 id="image-format-descriptor">Image Format Descriptor</h5> |
| <div class="paragraph"> |
| <p>The image format descriptor structure is defined as</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c"><span class="keyword">typedef</span> <span class="keyword">struct</span> cl_image_format { |
| cl_channel_order image_channel_order; |
| cl_channel_type image_channel_data_type; |
| } cl_image_format;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><code>image_channel_order</code> specifies the number of channels and the channel |
| layout i.e. the memory layout in which channels are stored in the image. |
| Valid values are described in the <a href="#image-channel-order-table">Image Channel |
| Order</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>image_channel_data_type</code> describes the size of the channel data type. |
| The list of supported values is described in the |
| <a href="#image-channel-data-types-table">Image Channel Data Types</a> table. |
| The number of bits per element determined by the <code>image_channel_data_type</code> |
| and <code>image_channel_order</code> must be a power of two.</p> |
| </div> |
| <table id="image-channel-order-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 14. List of supported Image Channel Order Values</caption> |
| <colgroup> |
| <col style="width: 100%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Enum values that can be specified in channel_order</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_R</strong>, <strong>CL_Rx</strong> or <strong>CL_A</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_INTENSITY</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_LUMINANCE</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEPTH</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_RG</strong>, <strong>CL_RGx</strong> or <strong>CL_RA</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_RGB</strong> or <strong>CL_RGBx</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_RGBA</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_sRGB</strong>, <strong>CL_sRGBx</strong>, <strong>CL_sRGBA</strong>, or <strong>CL_sBGRA</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_ARGB</strong>, <strong>CL_BGRA</strong>, or <strong>CL_ABGR</strong></p></td> |
| </tr> |
| </tbody> |
| </table> |
| <table id="image-channel-data-types-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 15. List of supported Image Channel Data Types</caption> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Image Channel Data Type</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SNORM_INT8</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is a normalized signed 8-bit integer value</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SNORM_INT16</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is a normalized signed 16-bit integer value</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNORM_INT8</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is a normalized unsigned 8-bit integer value</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNORM_INT16</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is a normalized unsigned 16-bit integer value</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNORM_SHORT_565</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Represents a normalized 5-6-5 3-channel RGB image. |
| The channel order must be CL_RGB or CL_RGBx.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNORM_SHORT_555</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Represents a normalized x-5-5-5 4-channel xRGB image. |
| The channel order must be CL_RGB or CL_RGBx.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNORM_INT_101010</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Represents a normalized x-10-10-10 4-channel xRGB image. |
| The channel order must be CL_RGB or CL_RGBx.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNORM_INT_101010_2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Represents a normalized 10-10-10-2 four-channel RGBA image. |
| The channel order must be CL_RGBA.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SIGNED_INT8</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is an unnormalized signed 8-bit integer value</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SIGNED_INT16</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is an unnormalized signed 16-bit integer value</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SIGNED_INT32</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is an unnormalized signed 32-bit integer value</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNSIGNED_INT8</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is an unnormalized unsigned 8-bit integer value</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNSIGNED_INT16</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is an unnormalized unsigned 16-bit integer value</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNSIGNED_INT32</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is an unnormalized unsigned 32-bit integer value</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_HALF_FLOAT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is a 16-bit half-float value</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLOAT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is a single precision floating-point value</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>For example, to specify a normalized unsigned 8-bit / channel RGBA image, |
| <code>image_channel_order</code> = CL_RGBA, and <code>image_channel_data_type</code> = |
| CL_UNORM_INT8. |
| The memory layout of this image format is described below:</p> |
| </div> |
| <table class="tableblock frame-all grid-all" style="width: 60%;"> |
| <colgroup> |
| <col style="width: 10%;"> |
| <col style="width: 10%;"> |
| <col style="width: 10%;"> |
| <col style="width: 10%;"> |
| <col style="width: 60%;"> |
| </colgroup> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">R</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">G</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">B</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">A</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">…​</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>with the corresponding byte offsets</p> |
| </div> |
| <table class="tableblock frame-all grid-all" style="width: 60%;"> |
| <colgroup> |
| <col style="width: 10%;"> |
| <col style="width: 10%;"> |
| <col style="width: 10%;"> |
| <col style="width: 10%;"> |
| <col style="width: 60%;"> |
| </colgroup> |
| <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">1</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">3</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">…​</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>Similar, if <code>image_channel_order</code> = CL_RGBA and <code>image_channel_data_type</code> = |
| CL_SIGNED_INT16, the memory layout of this image format is described below:</p> |
| </div> |
| <table class="tableblock frame-all grid-all" style="width: 60%;"> |
| <colgroup> |
| <col style="width: 10%;"> |
| <col style="width: 10%;"> |
| <col style="width: 10%;"> |
| <col style="width: 10%;"> |
| <col style="width: 60%;"> |
| </colgroup> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">R</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">G</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">B</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">A</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">…​</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>with the corresponding byte offsets</p> |
| </div> |
| <table class="tableblock frame-all grid-all" style="width: 60%;"> |
| <colgroup> |
| <col style="width: 10%;"> |
| <col style="width: 10%;"> |
| <col style="width: 10%;"> |
| <col style="width: 10%;"> |
| <col style="width: 60%;"> |
| </colgroup> |
| <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">2</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">6</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">…​</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p><code>image_channel_data_type</code> values of CL_UNORM_SHORT_565, CL_UNORM_SHORT_555, |
| CL_UNORM_INT_101010 and CL_UNORM_INT_101010_2 are special cases of packed |
| image formats where the channels of each element are packed into a single |
| unsigned short or unsigned int. |
| For these special packed image formats, the channels are normally packed |
| with the first channel in the most significant bits of the bitfield, and |
| successive channels occupying progressively less significant locations. |
| For CL_UNORM_SHORT_565, R is in bits 15:11, G is in bits 10:5 and B is in |
| bits 4:0. |
| For CL_UNORM_SHORT_555, bit 15 is undefined, R is in bits 14:10, G in bits |
| 9:5 and B in bits 4:0. |
| For CL_UNORM_INT_101010, bits 31:30 are undefined, R is in bits 29:20, G in |
| bits 19:10 and B in bits 9:0. |
| For CL_UNORM_INT_101010_2, R is in bits 31:22, G in bits 21:12, B in bits |
| 11:2 and A in bits 1:0.</p> |
| </div> |
| <div class="paragraph"> |
| <p>OpenCL implementations must maintain the minimum precision specified by the |
| number of bits in <code>image_channel_data_type</code>. |
| If the image format specified by <code>image_channel_order</code>, and |
| <code>image_channel_data_type</code> cannot be supported by the OpenCL implementation, |
| then the call to <strong>clCreateImage</strong> will return a <code>NULL</code> memory object.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="image-descriptor">Image Descriptor</h5> |
| <div class="paragraph"> |
| <p>The image descriptor structure describes the type and dimensions of the |
| image or image array and is defined as:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c"><span class="keyword">typedef</span> <span class="keyword">struct</span> cl_image_desc { |
| cl_mem_object_type image_type, |
| size_t image_width; |
| size_t image_height; |
| size_t image_depth; |
| size_t image_array_size; |
| size_t image_row_pitch; |
| size_t image_slice_pitch; |
| cl_uint num_mip_levels; |
| cl_uint num_samples; |
| cl_mem mem_object; |
| } cl_image_desc;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><code>image_type</code> describes the image type and must be either |
| CL_MEM_OBJECT_IMAGE1D, CL_MEM_OBJECT_IMAGE1D_BUFFER, |
| CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D, |
| CL_MEM_OBJECT_IMAGE2D_ARRAY or CL_MEM_OBJECT_IMAGE3D.</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>image_width</code> is the width of the image in pixels. |
| For a 2D image and image array, the image width must be a value ≥ 1 and |
| ≤ CL_DEVICE_IMAGE2D_MAX_WIDTH. |
| For a 3D image, the image width must be a value ≥1 and ≤ |
| CL_DEVICE_IMAGE3D_MAX_WIDTH. |
| For a 1D image buffer, the image width must be a value ≥1 and ≤ |
| CL_DEVICE_IMAGE_MAX_BUFFER_SIZE. |
| For a 1D image and 1D image array, the image width must be a value ≥1 |
| and ≤ CL_DEVICE_IMAGE2D_MAX_WIDTH.</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>image_height</code> is height of the image in pixels. |
| This is only used if the image is a 2D or 3D image, or a 2D image array. |
| For a 2D image or image array, the image height must be a value ≥ 1 and |
| ≤ CL_DEVICE_IMAGE2D_MAX_HEIGHT. |
| For a 3D image, the image height must be a value ≥ 1 and ≤ |
| CL_DEVICE_IMAGE3D_MAX_HEIGHT.</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>image_depth</code> is the depth of the image in pixels. |
| This is only used if the image is a 3D image and must be a value ≥ 1 and |
| ≤ CL_DEVICE_IMAGE3D_MAX_DEPTH.</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>image_array_size</code><sup>5</sup> is the number of images in the image array. |
| This is only used if the image is a 1D or 2D image array. |
| The values for <code>image_array_size</code>, if specified, must be a value ≥ 1 and |
| ≤ CL_DEVICE_IMAGE_MAX_ARRAY_SIZE.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">5</dt> |
| <dd> |
| <p>Note that reading and writing 2D image arrays from a kernel with |
| <code>image_array_size</code>=1 may be lower performance than 2D images.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p><code>image_row_pitch</code> is the scan-line pitch in bytes. |
| This must be 0 if <em>host_ptr</em> is <code>NULL</code> and can be either 0 or ≥ |
| <code>image_width</code> × size of element in bytes if <em>host_ptr</em> is not <code>NULL</code>. |
| If <em>host_ptr</em> is not <code>NULL</code> and <code>image_row_pitch</code> = 0, <code>image_row_pitch</code> is |
| calculated as <code>image_width</code> × size of element in bytes. |
| If <code>image_row_pitch</code> is not 0, it must be a multiple of the image element |
| size in bytes. |
| For a 2D image created from a buffer, the pitch specified (or computed if |
| pitch specified is 0) must be a multiple of the maximum of the |
| CL_DEVICE_IMAGE_PITCH_ALIGNMENT value for all devices in the context |
| associated with <code>image_desc</code>→`mem_object` and that support images.</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>image_slice_pitch</code> is the size in bytes of each 2D slice in the 3D image or |
| the size in bytes of each image in a 1D or 2D image array. |
| This must be 0 if <em>host_ptr</em> is <code>NULL</code>. |
| If <em>host_ptr</em> is not <code>NULL</code>, <code>image_slice_pitch</code> can be either 0 or ≥ |
| <code>image_row_pitch</code> × <code>image_height</code> for a 2D image array or 3D image |
| and can be either 0 or ≥ <code>image_row_pitch</code> for a 1D image array. |
| If <em>host_ptr</em> is not <code>NULL</code> and <code>image_slice_pitch</code> = 0, <code>image_slice_pitch</code> |
| is calculated as <code>image_row_pitch</code> × <code>image_height</code> for a 2D image |
| array or 3D image and <code>image_row_pitch</code> for a 1D image array. |
| If <code>image_slice_pitch</code> is not 0, it must be a multiple of the |
| <code>image_row_pitch</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>num_mip_levels and num_samples must be 0.</p> |
| </div> |
| <div class="paragraph"> |
| <p>mem_object may refer to a valid buffer or image memory object. |
| mem_object can be a buffer memory object if <code>image_type</code> is |
| CL_MEM_OBJECT_IMAGE1D_BUFFER or CL_MEM_OBJECT_IMAGE2D<sup>6</sup>. |
| mem_object can be an image object if <code>image_type</code> is |
| CL_MEM_OBJECT_IMAGE2D<sup>7</sup>. |
| Otherwise it must be <code>NULL</code>. |
| The image pixels are taken from the memory objects data store. |
| When the contents of the specified memory objects data store are modified, |
| those changes are reflected in the contents of the image object and |
| vice-versa at corresponding synchronization points.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">6</dt> |
| <dd> |
| <p>To create a 2D image from a buffer object that share the data store |
| between the image and buffer object.</p> |
| </dd> |
| <dt class="hdlist1">7</dt> |
| <dd> |
| <p>To create an image object from another image object that share the data |
| store between these image objects.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>For a 1D image buffer create from a buffer object, the <code>image_width</code> × |
| size of element in bytes must be ≤ size of the buffer object. |
| The image data in the buffer object is stored as a single scanline which is |
| a linear sequence of adjacent elements.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For a 2D image created from a buffer object, the <code>image_row_pitch</code> × |
| <code>image_height</code> must be ≤ size of the buffer object specified by |
| mem_object. |
| The image data in the buffer object is stored as a linear sequence of |
| adjacent scanlines. |
| Each scanline is a linear sequence of image elements padded to |
| <code>image_row_pitch</code> bytes.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For an image object created from another image object, the values specified |
| in the image descriptor except for mem_object must match the image |
| descriptor information associated with mem_object.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Image elements are stored according to their image format as described in |
| <a href="#image-format-descriptor">Image Format Descriptor</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the buffer object specified by mem_object is created with |
| CL_MEM_USE_HOST_PTR, the <em>host_ptr</em> specified to <strong>clCreateBuffer</strong> must be |
| aligned to the minimum of the <strong>CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT</strong> value |
| for all devices in the context associated with the buffer specified by |
| mem_object and that support images.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Creating a 2D image object from another 2D image object allows users to |
| create a new image object that shares the image data store with mem_object |
| but views the pixels in the image with a different channel order. |
| The restrictions are:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>all the values specified in `image_desc except for mem_object must match |
| the image descriptor information associated with mem_object.</p> |
| </li> |
| <li> |
| <p>The <em>`image_desc</em> used for creation of <em>mem_object</em> may not be |
| equivalent to image descriptor information associated with mem_object. |
| To ensure the values in <em>`image_desc</em> will match one can query |
| mem_object for associated information using <strong>clGetImageInfo</strong> function |
| described in <a href="#image-object-queries">Image Object Queries</a>.</p> |
| </li> |
| <li> |
| <p>the channel data type specified in <code>image_format</code> must match the channel |
| data type associated with mem_object. |
| The channel order values<sup>8</sup> supported are:</p> |
| <div class="openblock"> |
| <div class="content"> |
| <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"><code>image_channel_order</code> specified in <code>image_format</code></th> |
| <th class="tableblock halign-left valign-top">image channel order of mem_object</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_sBGRA</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_BGRA</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_BGRA</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_sBGRA</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_sRGBA</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_sRGBA</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_sRGB</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGB</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGB</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_sRGB</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_sRGBx</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBx</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBx</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_sRGBx</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEPTH</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_R</p></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| </li> |
| <li> |
| <p>the channel order specified must have the same number of channels as the |
| channel order of mem_object.</p> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">8</dt> |
| <dd> |
| <p>This allows developers to create a sRGB view of the image from a linear |
| RGB view or vice-versa i.e. the pixels stored in the image can be |
| accessed as linear RGB or sRGB values.</p> |
| </dd> |
| </dl> |
| </div> |
| </li> |
| </ul> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>Concurrent reading from, writing to and copying between both a buffer object |
| and 1D image buffer or 2D image object associated with the buffer object is |
| undefined. |
| Only reading from both a buffer object and 1D image buffer or 2D image |
| object associated with the buffer object is defined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Writing to an image created from a buffer and then reading from this buffer |
| in a kernel even if appropriate synchronization operations (such as a |
| barrier) are performed between the writes and reads is undefined. |
| Similarly, writing to the buffer and reading from the image created from |
| this buffer with appropriate synchronization between the writes and reads is |
| undefined.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_querying_list_of_supported_image_formats">5.3.2. Querying List of Supported Image Formats</h4> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetSupportedImageFormats(cl_context context, |
| cl_mem_flags flags, |
| cl_mem_object_type image_type, |
| cl_uint num_entries, |
| cl_image_format *image_formats, |
| cl_uint *num_image_formats)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>can be used to get the list of image formats supported by an OpenCL |
| implementation when the following information about an image memory object |
| is specified:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Context</p> |
| </li> |
| <li> |
| <p>Image type 1D, 2D, or 3D image, 1D image buffer, 1D or 2D image array.</p> |
| </li> |
| <li> |
| <p>Image object allocation information</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clGetSupportedImageFormats</strong> returns a union of image formats supported by |
| all devices in the context.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>context</em> is a valid OpenCL context on which the image object(s) will be |
| created.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>flags</em> is a bit-field that is used to specify allocation and usage |
| information about the image memory object being queried and is described in |
| the <a href="#memory-flags-table">Memory Flags</a> table. |
| To get a list of supported image formats that can be read from or written to |
| by a kernel, <em>flags</em> must be set to CL_MEM_READ_WRITE (get a list of images |
| that can be read from and written to by different kernel instances when |
| correctly ordered by event dependencies), CL_MEM_READ_ONLY (list of images |
| that can be read from by a kernel) or CL_MEM_WRITE_ONLY (list of images that |
| can be written to by a kernel). |
| To get a list of supported image formats that can be both read from and |
| written to by the same kernel instance, <em>flags</em> must be set to |
| CL_MEM_KERNEL_READ_AND_WRITE. |
| Please see <a href="#image-format-mapping">Image Format Mapping</a> for clarification.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>image_type</em> describes the image type and must be either |
| CL_MEM_OBJECT_IMAGE1D, CL_MEM_OBJECT_IMAGE1D_BUFFER, CL_MEM_OBJECT_IMAGE2D, |
| CL_MEM_OBJECT_IMAGE3D, CL_MEM_OBJECT_IMAGE1D_ARRAY or |
| CL_MEM_OBJECT_IMAGE2D_ARRAY.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>num_entries</em> specifies the number of entries that can be returned in the |
| memory location given by <em>image_formats</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>image_formats</em> is a pointer to a memory location where the list of |
| supported image formats are returned. |
| Each entry describes a <em>cl_image_format</em> structure supported by the OpenCL |
| implementation. |
| If <em>image_formats</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>num_image_formats</em> is the actual number of supported image formats for a |
| specific <em>context</em> and values specified by <em>flags</em>. |
| If <em>num_image_formats</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clGetSupportedImageFormats</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>flags</em> or <em>image_type</em> are not valid, or if |
| <em>num_entries</em> is 0 and <em>image_formats</em> is not <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>If CL_DEVICE_IMAGE_SUPPORT specified in the <a href="#device-queries-table">Device |
| Queries</a> table is CL_TRUE, the values assigned to |
| CL_DEVICE_MAX_READ_IMAGE_ARGS, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, |
| CL_DEVICE_IMAGE2D_MAX_WIDTH, CL_DEVICE_IMAGE2D_MAX_HEIGHT, |
| CL_DEVICE_IMAGE3D_MAX_WIDTH, CL_DEVICE_IMAGE3D_MAX_HEIGHT, |
| CL_DEVICE_IMAGE3D_MAX_DEPTH and CL_DEVICE_MAX_SAMPLERS by the implementation |
| must be greater than or equal to the minimum values specified in the |
| <a href="#device-queries-table">Device Queries</a> table.</p> |
| </div> |
| <div class="sect4"> |
| <h5 id="_minimum_list_of_supported_image_formats">Minimum List of Supported Image Formats</h5> |
| <div class="paragraph"> |
| <p>For 1D, 1D image from buffer, 2D, 3D image objects, 1D and 2D image array |
| objects, the mandated minimum list of image formats that can be read from |
| and written to by different kernel instances when correctly ordered by event |
| dependencies and that must be supported by all devices that support images |
| is described in the <a href="#min-supported-cross-kernel-table">Supported Formats - |
| Kernel Read Or Write</a> table.</p> |
| </div> |
| <table id="min-supported-cross-kernel-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 16. Min. list of supported image formats kernel read or write</caption> |
| <colgroup> |
| <col style="width: 34%;"> |
| <col style="width: 33%;"> |
| <col style="width: 33%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">num_channels</th> |
| <th class="tableblock halign-left valign-top">channel_order</th> |
| <th class="tableblock halign-left valign-top">channel_data_type</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_R</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_UNORM_INT8<br> |
| CL_UNORM_INT16<br> |
| CL_SNORM_INT8<br> |
| CL_SNORM_INT16<br> |
| CL_SIGNED_INT8<br> |
| CL_SIGNED_INT16<br> |
| CL_SIGNED_INT32<br> |
| CL_UNSIGNED_INT8<br> |
| CL_UNSIGNED_INT16<br> |
| CL_UNSIGNED_INT32<br> |
| CL_HALF_FLOAT<br> |
| CL_FLOAT</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">CL_DEPTH<sup>9</sup></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_UNORM_INT16<br> |
| CL_FLOAT</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">CL_RG</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_UNORM_INT8<br> |
| CL_UNORM_INT16<br> |
| CL_SNORM_INT8<br> |
| CL_SNORM_INT16<br> |
| CL_SIGNED_INT8<br> |
| CL_SIGNED_INT16<br> |
| CL_SIGNED_INT32<br> |
| CL_UNSIGNED_INT8<br> |
| CL_UNSIGNED_INT16<br> |
| CL_UNSIGNED_INT32<br> |
| CL_HALF_FLOAT<br> |
| CL_FLOAT</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">CL_RGBA</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_UNORM_INT8<br> |
| CL_UNORM_INT16<br> |
| CL_SNORM_INT8<br> |
| CL_SNORM_INT16<br> |
| CL_SIGNED_INT8<br> |
| CL_SIGNED_INT16<br> |
| CL_SIGNED_INT32<br> |
| CL_UNSIGNED_INT8<br> |
| CL_UNSIGNED_INT16<br> |
| CL_UNSIGNED_INT32<br> |
| CL_HALF_FLOAT<br> |
| CL_FLOAT</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">CL_BGRA</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_UNORM_INT8</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">CL_sRGBA</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_UNORM_INT8<sup>10</sup></p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">9</dt> |
| <dd> |
| <p>CL_DEPTH channel order is supported only for 2D image and 2D image array |
| objects.</p> |
| </dd> |
| <dt class="hdlist1">10</dt> |
| <dd> |
| <p>sRGB channel order support is not required for 1D image buffers. |
| Writes to images with sRGB channel orders requires device support of the |
| <strong>cl_khr_srgb_image_writes</strong> extension.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>For 1D, 1D image from buffer, 2D, 3D image objects, 1D and 2D image array |
| objects, the mandated minimum list of image formats that can be read from |
| and written to by the same kernel instance and that must be supported by all |
| devices that support images is described in the |
| <a href="#min-supported-same-kernel-table">Supported Formats - Kernel Read And |
| Write</a> table.</p> |
| </div> |
| <table id="min-supported-same-kernel-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 17. Min. list of supported image formats kernel read and write</caption> |
| <colgroup> |
| <col style="width: 34%;"> |
| <col style="width: 33%;"> |
| <col style="width: 33%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">num_channels</th> |
| <th class="tableblock halign-left valign-top">channel_order</th> |
| <th class="tableblock halign-left valign-top">channel_data_type</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_R</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_UNORM_INT8<br> |
| CL_SIGNED_INT8<br> |
| CL_SIGNED_INT16<br> |
| CL_SIGNED_INT32<br> |
| CL_UNSIGNED_INT8<br> |
| CL_UNSIGNED_INT16<br> |
| CL_UNSIGNED_INT32<br> |
| CL_HALF_FLOAT<br> |
| CL_FLOAT</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">CL_RGBA</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_UNORM_INT8<br> |
| CL_SIGNED_INT8<br> |
| CL_SIGNED_INT16<br> |
| CL_SIGNED_INT32<br> |
| CL_UNSIGNED_INT8<br> |
| CL_UNSIGNED_INT16<br> |
| CL_UNSIGNED_INT32<br> |
| CL_HALF_FLOAT<br> |
| CL_FLOAT</p></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| <div class="sect4"> |
| <h5 id="image-format-mapping">Image format mapping to OpenCL kernel language image access qualifiers</h5> |
| <div class="paragraph"> |
| <p>Image arguments to kernels may have the <code>read_only</code>, <code>write_only</code> or |
| <code>read_write</code> qualifier. |
| Not all image formats supported by the device and platform are valid to be |
| passed to all of these access qualifiers. |
| For each access qualifier, only images whose format is in the list of |
| formats returned by <strong>clGetSupportedImageFormats</strong> with the given flag |
| arguments in the <a href="#image-format-mapping-table">Image Format Mapping</a> table |
| are permitted. |
| It is not valid to pass an image supporting writing as both a <code>read_only</code> |
| image and a <code>write_only</code> image parameter, or to a <code>read_write</code> image |
| parameter and any other image parameter.</p> |
| </div> |
| <table id="image-format-mapping-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 18. Mapping from format flags passed to <strong>clGetSupportedImageFormats</strong> to OpenCL kernel language image access qualifiers</caption> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Access Qualifier</th> |
| <th class="tableblock halign-left valign-top">cl_mem_flags</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>read_only</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_MEM_READ_ONLY,<br> |
| CL_MEM_READ_WRITE,<br> |
| CL_MEM_KERNEL_READ_AND_WRITE</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>write_only</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_MEM_WRITE_ONLY,<br> |
| CL_MEM_READ_WRITE,<br> |
| CL_MEM_KERNEL_READ_AND_WRITE</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>read_write</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_MEM_KERNEL_READ_AND_WRITE</p></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_reading_writing_and_copying_image_objects">5.3.3. Reading, Writing and Copying Image Objects</h4> |
| <div class="paragraph"> |
| <p>The following functions enqueue commands to read from an image or image |
| array object to host memory or write to an image or image array object from |
| host memory.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueReadImage(cl_command_queue command_queue, |
| cl_mem image, |
| cl_bool blocking_read, |
| <span class="directive">const</span> size_t *origin, |
| <span class="directive">const</span> size_t *region, |
| size_t row_pitch, |
| size_t slice_pitch, |
| <span class="directive">void</span> *ptr, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueWriteImage(cl_command_queue command_queue, |
| cl_mem image, |
| cl_bool blocking_write, |
| <span class="directive">const</span> size_t *origin, |
| <span class="directive">const</span> size_t *region, |
| size_t input_row_pitch, |
| size_t input_slice_pitch, |
| <span class="directive">const</span> <span class="directive">void</span> *ptr, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> refers to the host command-queue in which the read / write |
| command will be queued. |
| <em>command_queue</em> and <em>image</em> must be created with the same OpenCL context.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>image</em> refers to a valid image or image array object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>blocking_read</em> and <em>blocking_write</em> indicate if the read and write |
| operations are <em>blocking</em> or <em>non-blocking</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_read</em> is CL_TRUE i.e. the read command is blocking, |
| <strong>clEnqueueReadImage</strong> does not return until the buffer data has been read and |
| copied into memory pointed to by <em>ptr</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_read</em> is CL_FALSE i.e. the read command is non-blocking, |
| <strong>clEnqueueReadImage</strong> queues a non-blocking read command and returns. |
| The contents of the buffer that <em>ptr</em> points to cannot be used until the |
| read command has completed. |
| The <em>event</em> argument returns an event object which can be used to query the |
| execution status of the read command. |
| When the read command has completed, the contents of the buffer that <em>ptr</em> |
| points to can be used by the application.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_write</em> is CL_TRUE, the write command is blocking and does not |
| return until the command is complete, including transfer of the data. |
| The memory pointed to by <em>ptr</em> can be reused by the application after the |
| <strong>clEnqueueWriteImage</strong> call returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_write</em> is CL_FALSE, the OpenCL implementation will use <em>ptr</em> to |
| perform a non-blocking write. |
| As the write is non-blocking the implementation can return immediately. |
| The memory pointed to by <em>ptr</em> cannot be reused by the application after the |
| call returns. |
| The <em>event</em> argument returns an event object which can be used to query the |
| execution status of the write command. |
| When the write command has completed, the memory pointed to by <em>ptr</em> can |
| then be reused by the application.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in pixels in the 1D, 2D or 3D |
| image, the (<em>x</em>, <em>y</em>) offset and the image index in the 2D image array or |
| the (<em>x</em>) offset and the image index in the 1D image array. |
| If <em>image</em> is a 2D image object, <em>origin</em>[2] must be 0. |
| If <em>image</em> is a 1D image or 1D image buffer object, <em>origin</em>[1] and |
| <em>origin</em>[2] must be 0. |
| If <em>image</em> is a 1D image array object, <em>origin</em>[2] must be 0. |
| If <em>image</em> is a 1D image array object, <em>origin</em>[1] describes the image index |
| in the 1D image array. |
| If <em>image</em> is a 2D image array object, <em>origin</em>[2] describes the image index |
| in the 2D image array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>region</em> defines the (<em>width</em>, <em>height</em>, <em>depth</em>) in pixels of the 1D, 2D or |
| 3D rectangle, the (<em>width</em>, <em>height</em>) in pixels of the 2D rectangle and the |
| number of images of a 2D image array or the (<em>width</em>) in pixels of the 1D |
| rectangle and the number of images of a 1D image array. |
| If <em>image</em> is a 2D image object, <em>region</em>[2] must be 1. |
| If <em>image</em> is a 1D image or 1D image buffer object, <em>region</em>[1] and |
| <em>region</em>[2] must be 1. |
| If <em>image</em> is a 1D image array object, <em>region</em>[2] must be 1. |
| The values in <em>region</em> cannot be 0.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>row_pitch</em> in <strong>clEnqueueReadImage</strong> and <em>input_row_pitch</em> in |
| <strong>clEnqueueWriteImage</strong> is the length of each row in bytes. |
| This value must be greater than or equal to the element size in bytes |
| × <em>width</em>. |
| If <em>row_pitch</em> (or <em>input_row_pitch</em>) is set to 0, the appropriate row pitch |
| is calculated based on the size of each element in bytes multiplied by |
| <em>width</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>slice_pitch</em> in <strong>clEnqueueReadImage</strong> and <em>input_slice_pitch</em> in |
| <strong>clEnqueueWriteImage</strong> is the size in bytes of the 2D slice of the 3D region |
| of a 3D image or each image of a 1D or 2D image array being read or written |
| respectively. |
| This must be 0 if <em>image</em> is a 1D or 2D image. |
| Otherwise this value must be greater than or equal to <em>row_pitch</em> × |
| <em>height</em>. |
| If <em>slice_pitch</em> (or <em>input_slice_pitch</em>) is set to 0, the appropriate slice |
| pitch is calculated based on the <em>row_pitch</em> × <em>height</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>ptr</em> is the pointer to a buffer in host memory where image data is to be |
| read from or to be written to. |
| The alignment requirements for ptr are specified in |
| <a href="#alignment-app-data-types">Alignment of Application Data Types</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait |
| on any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular read / write |
| command and can be used to query or queue a wait for this particular command |
| to complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueReadImage</strong> and <strong>clEnqueueWriteImage</strong> return CL_SUCCESS if the |
| function is executed successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em> and |
| <em>image</em> are not the same or if the context associated with |
| <em>command_queue</em> and events in <em>event_wait_list</em> are not the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if i_mage_ is not a valid image object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if the region being read or written specified by |
| <em>origin</em> and <em>region</em> is out of bounds or if <em>ptr</em> is a <code>NULL</code> value.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if values in <em>origin</em> and <em>region</em> do not follow rules |
| described in the argument description for <em>origin</em> and <em>region</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_IMAGE_SIZE if image dimensions (image width, height, |
| specified or compute row and/or slice pitch) for <em>image</em> are not |
| supported by device associated with <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and |
| data type) for <em>image</em> are not supported by device associated with |
| <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for data store associated with <em>image</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if the device associated with <em>command_queue</em> does |
| not support images (i.e. CL_DEVICE_IMAGE_SUPPORT specified in the |
| <a href="#device-queries-table">Device Queries</a> table is CL_FALSE).</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if <strong>clEnqueueReadImage</strong> is called on <em>image</em> which |
| has been created with CL_MEM_HOST_WRITE_ONLY or CL_MEM_HOST_NO_ACCESS.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if <strong>clEnqueueWriteImage</strong> is called on <em>image</em> which |
| has been created with CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_NO_ACCESS.</p> |
| </li> |
| <li> |
| <p>CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the read and write |
| operations are blocking and the execution status of any of the events in |
| <em>event_wait_list</em> is a negative integer value.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>Calling <strong>clEnqueueReadImage</strong> to read a region of the <em>image</em> with the <em>ptr</em> |
| argument value set to <em>host_ptr</em> + (<em>origin</em>[2] × <em>image slice pitch</em> |
| + <em>origin</em>[1] × <em>image row pitch</em> + <em>origin</em>[0] × <em>bytes |
| per pixel</em>), where <em>host_ptr</em> is a pointer to the memory region specified |
| when the <em>image</em> being read is created with CL_MEM_USE_HOST_PTR, must meet |
| the following requirements in order to avoid undefined behavior:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>All commands that use this image object have finished execution before |
| the read command begins execution.</p> |
| </li> |
| <li> |
| <p>The <em>row_pitch</em> and <em>slice_pitch</em> argument values in |
| <strong>clEnqueueReadImage</strong> must be set to the image row pitch and slice pitch.</p> |
| </li> |
| <li> |
| <p>The image object is not mapped.</p> |
| </li> |
| <li> |
| <p>The image object is not used by any command-queue until the read command |
| has finished execution.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Calling <strong>clEnqueueWriteImage</strong> to update the latest bits in a region of the |
| <em>image</em> with the <em>ptr</em> argument value set to <em>host_ptr</em> + (<em>origin</em>[2] |
| × <em>image slice pitch</em> + <em>origin</em>[1] × <em>image row pitch</em> + |
| <em>origin</em>[0] × <em>bytes per pixel</em>), where <em>host_ptr</em> is a pointer to the |
| memory region specified when the <em>image</em> being written is created with |
| CL_MEM_USE_HOST_PTR, must meet the following requirements in order to avoid |
| undefined behavior:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>The host memory region being written contains the latest bits when the |
| enqueued write command begins execution.</p> |
| </li> |
| <li> |
| <p>The <em>input_row_pitch</em> and <em>input_slice_pitch</em> argument values in |
| <strong>clEnqueueWriteImage</strong> must be set to the image row pitch and slice |
| pitch.</p> |
| </li> |
| <li> |
| <p>The image object is not mapped.</p> |
| </li> |
| <li> |
| <p>The image object is not used by any command-queue until the write |
| command has finished execution.</p> |
| </li> |
| </ul> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueCopyImage(cl_command_queue command_queue, |
| cl_mem src_image, |
| cl_mem dst_image, |
| <span class="directive">const</span> size_t *src_origin, |
| <span class="directive">const</span> size_t *dst_origin, |
| <span class="directive">const</span> size_t *region, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a command to copy image objects. |
| <em>src_image</em> and <em>dst_image</em> can be 1D, 2D, 3D image or a 1D, 2D image array |
| objects. |
| It is possible to copy subregions between any combinations of source and |
| destination types, provided that the dimensions of the subregions are the |
| same e.g., one can copy a rectangular region from a 2D image to a slice of a |
| 3D image.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> refers to the host command-queue in which the copy command |
| will be queued. |
| The OpenCL context associated with <em>command_queue</em>, <em>src_image</em> and |
| <em>dst_image</em> must be the same.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>src_origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in pixels in the 1D, 2D or |
| 3D image, the (<em>x</em>, <em>y</em>) offset and the image index in the 2D image array or |
| the (<em>x</em>) offset and the image index in the 1D image array. |
| If <em>image</em> is a 2D image object, <em>src_origin</em>[2] must be 0. |
| If <em>src_image</em> is a 1D image object, <em>src_origin</em>[1] and <em>src_origin</em>[2] |
| must be 0. |
| If <em>src_image</em> is a 1D image array object, <em>src_origin</em>[2] must be 0. |
| If <em>src_image</em> is a 1D image array object, <em>src_origin</em>[1] describes the |
| image index in the 1D image array. |
| If <em>src_image</em> is a 2D image array object, <em>src_origin</em>[2] describes the |
| image index in the 2D image array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>dst_origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in pixels in the 1D, 2D or |
| 3D image, the (<em>x</em>, <em>y</em>) offset and the image index in the 2D image array or |
| the (<em>x</em>) offset and the image index in the 1D image array. |
| If <em>dst_image</em> is a 2D image object, <em>dst_origin</em>[2] must be 0. |
| If <em>dst_image</em> is a 1D image or 1D image buffer object, <em>dst_origin</em>[1] and |
| <em>dst_origin</em>[2] must be 0. |
| If <em>dst_image</em> is a 1D image array object, <em>dst_origin</em>[2] must be 0. |
| If <em>dst_image</em> is a 1D image array object, <em>dst_origin</em>[1] describes the |
| image index in the 1D image array. |
| If <em>dst_image</em> is a 2D image array object, <em>dst_origin</em>[2] describes the |
| image index in the 2D image array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>region</em> defines the (<em>width</em>, <em>height</em>, <em>depth</em>) in pixels of the 1D, 2D or |
| 3D rectangle, the (<em>width</em>, <em>height</em>) in pixels of the 2D rectangle and the |
| number of images of a 2D image array or the (<em>width</em>) in pixels of the 1D |
| rectangle and the number of images of a 1D image array. |
| If <em>src_image</em> or <em>dst_image</em> is a 2D image object, <em>region</em>[2] must be 1. |
| If <em>src_image</em> or <em>dst_image</em> is a 1D image or 1D image buffer object, |
| <em>region</em>[1] and <em>region</em>[2] must be 1. |
| If <em>src_image</em> or <em>dst_image</em> is a 1D image array object, <em>region</em>[2] must |
| be 1. |
| The values in <em>region</em> cannot be 0.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait |
| on any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular copy command |
| and can be used to query or queue a wait for this particular command to |
| complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| <strong>clEnqueueBarrierWithWaitList</strong> can be used instead. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is currently a requirement that the <em>src_image</em> and <em>dst_image</em> image |
| memory objects for <strong>clEnqueueCopyImage</strong> must have the exact same image |
| format (i.e. the cl_image_format descriptor specified when <em>src_image</em> and |
| <em>dst_image</em> are created must match).</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueCopyImage</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em>, |
| <em>src_image</em> and <em>dst_image</em> are not the same or if the context |
| associated with <em>command_queue</em> and events in <em>event_wait_list</em> are not |
| the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>src_image</em> and <em>dst_image</em> are not valid image |
| objects.</p> |
| </li> |
| <li> |
| <p>CL_IMAGE_FORMAT_MISMATCH if <em>src_image</em> and <em>dst_image</em> do not use the |
| same image format.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if the 2D or 3D rectangular region specified by |
| <em>src_origin</em> and <em>src_origin</em> + <em>region</em> refers to a region outside |
| <em>src_image</em>, or if the 2D or 3D rectangular region specified by |
| <em>dst_origin</em> and <em>dst_origin</em> + <em>region</em> refers to a region outside |
| <em>dst_image</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if values in <em>src_origin</em>, <em>dst_origin</em> and <em>region</em> do |
| not follow rules described in the argument description for <em>src_origin</em>, |
| <em>dst_origin</em> and <em>region</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_IMAGE_SIZE if image dimensions (image width, height, |
| specified or compute row and/or slice pitch) for <em>src_image</em> or |
| <em>dst_image</em> are not supported by device associated with <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and |
| data type) for <em>src_image</em> or <em>dst_image</em> are not supported by device |
| associated with <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for data store associated with <em>src_image</em> or <em>dst_image</em>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if the device associated with <em>command_queue</em> does |
| not support images (i.e. CL_DEVICE_IMAGE_SUPPORT specified in the |
| <a href="#device-queries-table">Device Queries</a> table is CL_FALSE).</p> |
| </li> |
| <li> |
| <p>CL_MEM_COPY_OVERLAP if <em>src_image</em> and <em>dst_image</em> are the same image |
| object and the source and destination regions overlap.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_filling_image_objects">5.3.4. Filling Image Objects</h4> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueFillImage(cl_command_queue command_queue, |
| cl_mem image, |
| <span class="directive">const</span> <span class="directive">void</span> *fill_color, |
| <span class="directive">const</span> size_t *origin, |
| <span class="directive">const</span> size_t *region, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a command to fill an image object with a specified color. |
| The usage information which indicates whether the memory object can be read |
| or written by a kernel and/or the host and is given by the cl_mem_flags |
| argument value specified when <em>image</em> is created is ignored by |
| <strong>clEnqueueFillImage</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> refers to the host command-queue in which the fill command |
| will be queued. |
| The OpenCL context associated with <em>command_queue</em> and <em>image</em> must be the |
| same.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>image</em> is a valid image object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>fill_color</em> is the color used to fill the image. |
| The fill color is a single floating point value if the channel order is |
| CL_DEPTH. |
| Otherwise, the fill color is a four component RGBA floating-point color |
| value if the <em>image</em> channel data type is not an unnormalized signed or |
| unsigned integer type, is a four component signed integer value if the |
| <em>image</em> channel data type is an unnormalized signed integer type and is a |
| four component unsigned integer value if the <em>image</em> channel data type is an |
| unnormalized unsigned integer type. |
| The fill color will be converted to the appropriate image channel format and |
| order associated with <em>image</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in pixels in the 1D, 2D or 3D |
| image, the (<em>x</em>, <em>y</em>) offset and the image index in the 2D image array or |
| the (<em>x</em>) offset and the image index in the 1D image array. |
| If <em>image</em> is a 2D image object, <em>origin</em>[2] must be 0. |
| If <em>image</em> is a 1D image or 1D image buffer object, <em>origin</em>[1] and |
| <em>origin</em>[2] must be 0. |
| If <em>image</em> is a 1D image array object, <em>origin</em>[2] must be 0. |
| If <em>image</em> is a 1D image array object, <em>origin</em>[1] describes the image index |
| in the 1D image array. |
| If <em>image</em> is a 2D image array object, <em>origin</em>[2] describes the image index |
| in the 2D image array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>region</em> defines the (<em>width</em>, <em>height</em>, <em>depth</em>) in pixels of the 1D, 2D or |
| 3D rectangle, the (<em>width</em>, <em>height</em>) in pixels of the 2D rectangle and the |
| number of images of a 2D image array or the (<em>width</em>) in pixels of the 1D |
| rectangle and the number of images of a 1D image array. |
| If <em>image</em> is a 2D image object, <em>region</em>[2] must be 1. |
| If <em>image</em> is a 1D image or 1D image buffer object, <em>region</em>[1] and |
| <em>region</em>[2] must be 1. |
| If <em>image</em> is a 1D image array object, <em>region</em>[2] must be 1. |
| The values in <em>region</em> cannot be 0.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait |
| on any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular command and |
| can be used to query or queue a wait for this particular command to |
| complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| <strong>clEnqueueBarrierWithWaitList</strong> can be used instead. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueFillImage</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em> and |
| <em>image</em> are not the same or if the context associated with |
| <em>command_queue</em> and events in <em>event_wait_list</em> are not the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>image</em> is not a valid image object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>fill_color</em> is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if the region being filled as specified by <em>origin</em> and |
| <em>region</em> is out of bounds or if <em>ptr</em> is a <code>NULL</code> value.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if values in <em>origin</em> and <em>region</em> do not follow rules |
| described in the argument description for <em>origin</em> and <em>region</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_IMAGE_SIZE if image dimensions (image width, height, |
| specified or compute row and/or slice pitch) for <em>image</em> are not |
| supported by device associated with <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and |
| data type) for <em>image</em> are not supported by device associated with |
| <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for data store associated with <em>image</em>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_copying_between_image_and_buffer_objects">5.3.5. Copying between Image and Buffer Objects</h4> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueCopyImageToBuffer(cl_command_queue command_queue, |
| cl_mem src_image, |
| cl_mem dst_buffer, |
| <span class="directive">const</span> size_t *src_origin, |
| <span class="directive">const</span> size_t *region, |
| size_t dst_offset, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a command to copy an image object to a buffer object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> must be a valid host command-queue. |
| The OpenCL context associated with <em>command_queue</em>, <em>src_image</em> and |
| <em>dst_buffer</em> must be the same.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>src_image</em> is a valid image object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>dst_buffer</em> is a valid buffer object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>src_origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in pixels in the 1D, 2D or |
| 3D image, the (<em>x</em>, <em>y</em>) offset and the image index in the 2D image array or |
| the (<em>x</em>) offset and the image index in the 1D image array. |
| If <em>src_image</em> is a 2D image object, <em>src_origin</em>[2] must be 0. |
| If <em>src_image</em> is a 1D image or 1D image buffer object, <em>src_origin</em>[1] and |
| <em>src_origin</em>[2] must be 0. |
| If <em>src_image</em> is a 1D image array object, <em>src_origin</em>[2] must be 0. |
| If <em>src_image</em> is a 1D image array object, <em>src_origin</em>[1] describes the |
| image index in the 1D image array. |
| If <em>src_image</em> is a 2D image array object, <em>src_origin</em>[2] describes the |
| image index in the 2D image array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>region</em> defines the (<em>width</em>, <em>height</em>, <em>depth</em>) in pixels of the 1D, 2D or |
| 3D rectangle, the (<em>width</em>, <em>height</em>) in pixels of the 2D rectangle and the |
| number of images of a 2D image array or the (<em>width</em>) in pixels of the 1D |
| rectangle and the number of images of a 1D image array. |
| If <em>src_image</em> is a 2D image object, <em>region</em>[2] must be 1. |
| If <em>src_image</em> is a 1D image or 1D image buffer object, <em>region</em>[1] and |
| <em>region</em>[2] must be 1. |
| If <em>src_image</em> is a 1D image array object, <em>region</em>[2] must be 1. |
| The values in <em>region</em> cannot be 0.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>dst_offset</em> refers to the offset where to begin copying data into |
| <em>dst_buffer</em>. |
| The size in bytes of the region to be copied referred to as <em>dst_cb</em> is |
| computed as <em>width</em> × <em>height</em> × <em>depth</em> × <em>bytes/image |
| element</em> if <em>src_image</em> is a 3D image object, is computed as <em>width</em> × |
| <em>height</em> × <em>bytes/image element</em> if <em>src_image</em> is a 2D image, is |
| computed as <em>width</em> × <em>height</em> × <em>arraysize</em> × |
| <em>bytes/image element</em> if <em>src_image</em> is a 2D image array object, is computed |
| as <em>width</em> × <em>bytes/image element</em> if <em>src_image</em> is a 1D image or 1D |
| image buffer object and is computed as <em>width</em> × <em>arraysize</em> × |
| <em>bytes/image element</em> if <em>src_image</em> is a 1D image array object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait |
| on any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular copy command |
| and can be used to query or queue a wait for this particular command to |
| complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| <strong>clEnqueueBarrierWithWaitList</strong> can be used instead. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueCopyImageToBuffer</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em>, |
| <em>src_image</em> and <em>dst_buffer</em> are not the same or if the context |
| associated with <em>command_queue</em> and events in <em>event_wait_list</em> are not |
| the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>src_image</em> is not a valid image object or |
| <em>dst_buffer</em> is not a valid buffer object or if <em>src_image</em> is a 1D |
| image buffer object created from <em>dst_buffer</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if the 1D, 2D or 3D rectangular region specified by |
| <em>src_origin</em> and <em>src_origin</em> + <em>region</em> refers to a region outside |
| <em>src_image</em>, or if the region specified by <em>dst_offset</em> and <em>dst_offset</em> |
| + <em>dst_cb</em> to a region outside <em>dst_buffer</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if values in <em>src_origin</em> and <em>region</em> do not follow |
| rules described in the argument description for <em>src_origin</em> and |
| <em>region</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>dst_buffer</em> is a sub-buffer object |
| and <em>offset</em> specified when the sub-buffer object is created is not |
| aligned to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated |
| with <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_IMAGE_SIZE if image dimensions (image width, height, |
| specified or compute row and/or slice pitch) for <em>src_image</em> are not |
| supported by device associated with <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and |
| data type) for <em>src_image</em> are not supported by device associated with |
| <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for data store associated with <em>src_image</em> or <em>dst_buffer</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if the device associated with <em>command_queue</em> does |
| not support images (i.e. CL_DEVICE_IMAGE_SUPPORT specified in the |
| <a href="#device-queries-table">Device Queries</a> table is CL_FALSE).</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueCopyBufferToImage(cl_command_queue command_queue, |
| cl_mem src_buffer, |
| cl_mem dst_image, |
| size_t src_offset, |
| <span class="directive">const</span> size_t *dst_origin, |
| <span class="directive">const</span> size_t *region, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a command to copy a buffer object to an image object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> must be a valid host command-queue. |
| The OpenCL context associated with <em>command_queue</em>, <em>src_buffer</em> and |
| <em>dst_image</em> must be the same.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>src_buffer</em> is a valid buffer object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>dst_image</em> is a valid image object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>src_offset</em> refers to the offset where to begin copying data from |
| <em>src_buffer</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>dst_origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in pixels in the 1D, 2D or |
| 3D image, the (<em>x</em>, <em>y</em>) offset and the image index in the 2D image array or |
| the (<em>x</em>) offset and the image index in the 1D image array. |
| If <em>dst_image</em> is a 2D image object, <em>dst_origin</em>[2] must be 0. |
| If <em>dst_image</em> is a 1D image or 1D image buffer object, <em>dst_origin</em>[1] and |
| <em>dst_origin</em>[2] must be 0. |
| If <em>dst_image</em> is a 1D image array object, <em>dst_origin</em>[2] must be 0. |
| If <em>dst_image</em> is a 1D image array object, <em>dst_origin</em>[1] describes the |
| image index in the 1D image array. |
| If <em>dst_image</em> is a 2D image array object, <em>dst_origin</em>[2] describes the |
| image index in the 2D image array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>region</em> defines the (<em>width</em>, <em>height</em>, <em>depth</em>) in pixels of the 1D, 2D or |
| 3D rectangle, the (<em>width</em>, <em>height</em>) in pixels of the 2D rectangle and the |
| number of images of a 2D image array or the (<em>width</em>) in pixels of the 1D |
| rectangle and the number of images of a 1D image array. |
| If <em>dst_image</em> is a 2D image object, <em>region</em>[2] must be 1. |
| If <em>dst_image</em> is a 1D image or 1D image buffer object, <em>region</em>[1] and |
| <em>region</em>[2] must be 1. |
| If <em>dst_image</em> is a 1D image array object, <em>region</em>[2] must be 1. |
| The values in <em>region</em> cannot be 0.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The size in bytes of the region to be copied from <em>src_buffer</em> referred to |
| as <em>src_cb</em> is computed as <em>width</em> × <em>height</em> × <em>depth</em> × |
| <em>bytes/image element</em> if <em>dst_image</em> is a 3D image object, is computed as |
| <em>width</em> × <em>height</em> × <em>bytes/image element</em> if <em>dst_image</em> is a |
| 2D image, is computed as <em>width</em> × <em>height</em> × <em>arraysize</em> |
| × <em>bytes/image element</em> if <em>dst_image</em> is a 2D image array object, is |
| computed as <em>width</em> × <em>bytes/image element</em> if <em>dst_image</em> is a 1D |
| image or 1D image buffer object and is computed as <em>width</em> × |
| <em>arraysize</em> × <em>bytes/image element</em> if <em>dst_image</em> is a 1D image array |
| object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait |
| on any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular copy command |
| and can be used to query or queue a wait for this particular command to |
| complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| <strong>clEnqueueBarrierWithWaitList</strong> can be used instead. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueCopyBufferToImage</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em>, |
| <em>src_buffer</em> and <em>dst_image</em> are not the same or if the context |
| associated with <em>command_queue</em> and events in <em>event_wait_list</em> are not |
| the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>src_buffer</em> is not a valid buffer object or |
| <em>dst_image</em> is not a valid image object or if <em>dst_image</em> is a 1D image |
| buffer object created from <em>src_buffer</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if the 1D, 2D or 3D rectangular region specified by |
| <em>dst_origin</em> and <em>dst_origin</em> + <em>region</em> refer to a region outside |
| <em>dst_image</em>, or if the region specified by <em>src_offset</em> and <em>src_offset</em> |
| + <em>src_cb</em> refer to a region outside <em>src_buffer</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if values in <em>dst_origin</em> and <em>region</em> do not follow |
| rules described in the argument description for <em>dst_origin</em> and |
| <em>region</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>src_buffer</em> is a sub-buffer object |
| and <em>offset</em> specified when the sub-buffer object is created is not |
| aligned to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated |
| with <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_IMAGE_SIZE if image dimensions (image width, height, |
| specified or compute row and/or slice pitch) for <em>dst_image</em> are not |
| supported by device associated with <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and |
| data type) for <em>dst_image</em> are not supported by device associated with |
| <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for data store associated with <em>src_buffer</em> or <em>dst_image</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if the device associated with <em>command_queue</em> does |
| not support images (i.e. CL_DEVICE_IMAGE_SUPPORT specified in the |
| <a href="#device-queries-table">Device Queries</a> table is CL_FALSE).</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_mapping_image_objects">5.3.6. Mapping Image Objects</h4> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c"><span class="directive">void</span>* clEnqueueMapImage(cl_command_queue command_queue, |
| cl_mem image, |
| cl_bool blocking_map, |
| cl_map_flags map_flags, |
| <span class="directive">const</span> size_t *origin, |
| <span class="directive">const</span> size_t *region, |
| size_t *image_row_pitch, |
| size_t *image_slice_pitch, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event, |
| cl_int *errcode_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a command to map a region in the image object given by <em>image</em> into |
| the host address space and returns a pointer to this mapped region.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> must be a valid host command-queue.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>image</em> is a valid image object. |
| The OpenCL context associated with <em>command_queue</em> and <em>image</em> must be the |
| same.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>blocking_map</em> indicates if the map operation is <em>blocking</em> or |
| <em>non-blocking</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_map</em> is CL_TRUE, <strong>clEnqueueMapImage</strong> does not return until the |
| specified region in <em>image</em> is mapped into the host address space and the |
| application can access the contents of the mapped region using the pointer |
| returned by <strong>clEnqueueMapImage</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_map</em> is CL_FALSE i.e. map operation is non-blocking, the |
| pointer to the mapped region returned by <strong>clEnqueueMapImage</strong> cannot be used |
| until the map command has completed. |
| The <em>event</em> argument returns an event object which can be used to query the |
| execution status of the map command. |
| When the map command is completed, the application can access the contents |
| of the mapped region using the pointer returned by <strong>clEnqueueMapImage</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>map_flags</em> is a bit-field and is described in the |
| <a href="#memory-map-flags-table">Memory Map Flags</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in pixels in the 1D, 2D or 3D |
| image, the (<em>x</em>, <em>y</em>) offset and the image index in the 2D image array or |
| the (<em>x</em>) offset and the image index in the 1D image array. |
| If <em>image</em> is a 2D image object, <em>origin</em>[2] must be 0. |
| If <em>image</em> is a 1D image or 1D image buffer object, <em>origin</em>[1] and |
| <em>origin</em>[2] must be 0. |
| If <em>image</em> is a 1D image array object, <em>origin</em>[2] must be 0. |
| If <em>image</em> is a 1D image array object, <em>origin</em>[1] describes the image index |
| in the 1D image array. |
| If <em>image</em> is a 2D image array object, <em>origin</em>[2] describes the image index |
| in the 2D image array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>region</em> defines the (<em>width</em>, <em>height</em>, <em>depth</em>) in pixels of the 1D, 2D or |
| 3D rectangle, the (<em>width</em>, <em>height</em>) in pixels of the 2D rectangle and the |
| number of images of a 2D image array or the (<em>width</em>) in pixels of the 1D |
| rectangle and the number of images of a 1D image array. |
| If <em>image</em> is a 2D image object, <em>region</em>[2] must be 1. |
| If <em>image</em> is a 1D image or 1D image buffer object, <em>region</em>[1] and |
| <em>region</em>[2] must be 1. |
| If <em>image</em> is a 1D image array object, <em>region</em>[2] must be 1. |
| The values in <em>region</em> cannot be 0.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>image_row_pitch</em> returns the scan-line pitch in bytes for the mapped |
| region. |
| This must be a non-<code>NULL</code> value.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>image_slice_pitch</em> returns the size in bytes of each 2D slice of a 3D image |
| or the size of each 1D or 2D image in a 1D or 2D image array for the mapped |
| region. |
| For a 1D and 2D image, zero is returned if this argument is not <code>NULL</code>. |
| For a 3D image, 1D and 2D image array, <em>image_slice_pitch</em> must be a |
| non-<code>NULL</code> value.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before <strong>clEnqueueMapImage</strong> can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then <strong>clEnqueueMapImage</strong> does not wait on |
| any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular command and |
| can be used to query or queue a wait for this particular command to |
| complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>errcode_ret</em> will return an appropriate error code. |
| If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueMapImage</strong> will return a pointer to the mapped region. |
| The <em>errcode_ret</em> is set to CL_SUCCESS.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A <code>NULL</code> pointer is returned otherwise with one of the following error |
| values returned in <em>errcode_ret</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and |
| <em>image</em> are not the same or if context associated with <em>command_queue</em> |
| and events in <em>event_wait_list</em> are not the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>image</em> is not a valid image object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if region being mapped given by (<em>origin</em>, |
| <em>origin+region</em>) is out of bounds or if values specified in <em>map_flags</em> |
| are not valid.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if values in <em>origin</em> and <em>region</em> do not follow rules |
| described in the argument description for <em>origin</em> and <em>region</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>image_row_pitch</em> is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>image</em> is a 3D image, 1D or 2D image array object |
| and <em>image_slice_pitch</em> is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_IMAGE_SIZE if image dimensions (image width, height, |
| specified or compute row and/or slice pitch) for <em>image</em> are not |
| supported by device associated with <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and |
| data type) for <em>image</em> are not supported by device associated with |
| <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_MAP_FAILURE if there is a failure to map the requested region into |
| the host address space. |
| This error cannot occur for image objects created with |
| CL_MEM_USE_HOST_PTR or CL_MEM_ALLOC_HOST_PTR.</p> |
| </li> |
| <li> |
| <p>CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the map operation is |
| blocking and the execution status of any of the events in |
| <em>event_wait_list</em> is a negative integer value.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for data store associated with <em>image</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if the device associated with <em>command_queue</em> does |
| not support images (i.e. CL_DEVICE_IMAGE_SUPPORT specified in the |
| <a href="#device-queries-table">Device Queries</a> table is CL_FALSE).</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if <em>image</em> has been created with |
| CL_MEM_HOST_WRITE_ONLY or CL_MEM_HOST_NO_ACCESS and CL_MAP_READ is set |
| in <em>map_flags</em> or if <em>image</em> has been created with CL_MEM_HOST_READ_ONLY |
| or CL_MEM_HOST_NO_ACCESS and CL_MAP_WRITE or |
| CL_MAP_WRITE_INVALIDATE_REGION is set in <em>map_flags</em>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if mapping would lead to overlapping regions being |
| mapped for writing.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The pointer returned maps a 1D, 2D or 3D region starting at <em>origin</em> and is |
| at least <em>region</em>[0] pixels in size for a 1D image, 1D image buffer or 1D |
| image array, (<em>image_row_pitch × region[1])</em> pixels in size for a 2D |
| image or 2D image array, and (<em>image_slice_pitch × region[2])</em> pixels |
| in size for a 3D image. |
| The result of a memory access outside this region is undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the image object is created with CL_MEM_USE_HOST_PTR set in <em>mem_flags</em>, |
| the following will be true:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>The <em>host_ptr</em> specified in <strong>clCreateImage</strong> is guaranteed to contain the |
| latest bits in the region being mapped when the <strong>clEnqueueMapImage</strong> |
| command has completed.</p> |
| </li> |
| <li> |
| <p>The pointer value returned by <strong>clEnqueueMapImage</strong> will be derived from |
| the <em>host_ptr</em> specified when the image object is created.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Mapped image objects are unmapped using <strong>clEnqueueUnmapMemObject</strong>. |
| This is described in <a href="#unmapping-mapped-memory">Unmapping Mapped Memory |
| Objects</a>.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="image-object-queries">5.3.7. Image Object Queries</h4> |
| <div class="paragraph"> |
| <p>To get information that is common to all memory objects, use the |
| <strong>clGetMemObjectInfo</strong> function described in <a href="#memory-object-queries">Memory |
| Object Queries</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To get information specific to an image object created with <strong>clCreateImage</strong>, |
| use the following function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetImageInfo(cl_mem image, |
| cl_image_info param_name, |
| size_t param_value_size, |
| <span class="directive">void</span> *param_value, |
| size_t *param_value_size_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><em>image</em> specifies the image object being queried.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_name</em> specifies the information to query. |
| The list of supported <em>param_name</em> types and the information returned in |
| <em>param_value</em> by <strong>clGetImageInfo</strong> is described in the |
| <a href="#image-info-table">Image Object Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value</em> is a pointer to memory where the appropriate result being |
| queried is returned. |
| If <em>param_value</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to |
| by <em>param_value</em>. |
| This size must be ≥ size of return type as described in the |
| <a href="#image-info-table">Image Object Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size_ret</em> returns the actual size in bytes of data being |
| queried by <em>param_name</em>. |
| If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clGetImageInfo</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes |
| specified by <em>param_value_size</em> is < size of return type as described in |
| the <a href="#image-info-table">Image Object Queries</a> table and <em>param_value</em> is |
| not <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>image</em> is a not a valid image object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <table id="image-info-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 19. List of supported param_names by <strong>clGetImageInfo</strong></caption> |
| <colgroup> |
| <col style="width: 34%;"> |
| <col style="width: 33%;"> |
| <col style="width: 33%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_image_info</strong></th> |
| <th class="tableblock halign-left valign-top">Return type</th> |
| <th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_FORMAT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_image_format</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return image format descriptor specified when <em>image</em> is created |
| with <strong>clCreateImage</strong>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_ELEMENT_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return size of each element of the image memory object given by |
| <em>image</em> in bytes. |
| An element is made up of <em>n</em> channels. |
| The value of <em>n</em> is given in <em>cl_image_format</em> descriptor.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_ROW_PITCH</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return calculated row pitch in bytes of a row of elements of the |
| image object given by <em>image</em>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_SLICE_PITCH</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return calculated slice pitch in bytes of a 2D slice for the 3D |
| image object or size of each image in a 1D or 2D image array given |
| by <em>image</em>. |
| For a 1D image, 1D image buffer and 2D image object return 0.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_WIDTH</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return width of the image in pixels.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_HEIGHT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return height of the image in pixels. |
| For a 1D image, 1D image buffer and 1D image array object, height = |
| 0.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_DEPTH</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return depth of the image in pixels. |
| For a 1D image, 1D image buffer, 2D image or 1D and 2D image array |
| object, depth = 0.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_ARRAY_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return number of images in the image array. |
| If <em>image</em> is not an image array, 0 is returned.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_NUM_MIP_LEVELS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return num_mip_levels associated with <em>image</em>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_NUM_SAMPLES</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return num_samples associated with <em>image</em>.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_pipes">5.4. Pipes</h3> |
| <div class="paragraph"> |
| <p>A <em>pipe</em> is a memory object that stores data organized as a FIFO. |
| Pipe objects can only be accessed using built-in functions that read from |
| and write to a pipe. |
| Pipe objects are not accessible from the host. |
| A pipe object encapsulates the following information:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Packet size in bytes</p> |
| </li> |
| <li> |
| <p>Maximum capacity in packets</p> |
| </li> |
| <li> |
| <p>Information about the number of packets currently in the pipe</p> |
| </li> |
| <li> |
| <p>Data packets</p> |
| </li> |
| </ul> |
| </div> |
| <div class="sect3"> |
| <h4 id="_creating_pipe_objects">5.4.1. Creating Pipe Objects</h4> |
| <div class="paragraph"> |
| <p>A <strong>pipe object</strong> is created using the following function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_mem clCreatePipe(cl_context context, |
| cl_mem_flags flags, |
| cl_uint pipe_packet_size, |
| cl_uint pipe_max_packets, |
| <span class="directive">const</span> cl_pipe_properties *properties, |
| cl_int *errcode_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><em>context</em> is a valid OpenCL context used to create the pipe object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>flags</em> is a bit-field that is used to specify allocation and usage |
| information such as the memory arena that should be used to allocate the |
| pipe object and how it will be used. |
| The <a href="#memory-flags">Memory Flags</a> table describes the possible values for |
| <em>flags</em>. |
| Only CL_MEM_READ_WRITE and CL_MEM_HOST_NO_ACCESS can be specified when |
| creating a pipe object. |
| If the value specified for <em>flags</em> is 0, the default is used which is |
| CL_MEM_READ_WRITE | CL_MEM_HOST_NO_ACCESS.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>pipe_packet_size</em> is the size in bytes of a pipe packet.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>pipe_max_packets</em> specifies the pipe capacity by specifying the maximum |
| number of packets the pipe can hold.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>properties</em> specifies a list of properties for the pipe and their |
| corresponding values. |
| Each property name is immediately followed by the corresponding desired |
| value. |
| The list is terminated with 0. |
| In OpenCL 2.2, <em>properties</em> must be <code>NULL</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>errcode_ret</em> will return an appropriate error code. |
| If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreatePipe</strong> returns a valid non-zero pipe object and <em>errcode_ret</em> is set |
| to CL_SUCCESS if the pipe object is created successfully. |
| Otherwise, it returns a <code>NULL</code> value with one of the following error values |
| returned in <em>errcode_ret</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if values specified in <em>flags</em> are not as defined |
| above.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>properties</em> is not <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_PIPE_SIZE if <em>pipe_packet_size</em> is 0 or the |
| <em>pipe_packet_size</em> exceeds CL_DEVICE_PIPE_MAX_PACKET_SIZE value |
| specified in the <a href="#device-queries-table">Device Queries</a> table for all |
| devices in <em>context</em> or if <em>pipe_max_packets</em> is 0.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for the pipe object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Pipes follow the same memory consistency model as defined for buffer and |
| image objects. |
| The pipe state i.e. contents of the pipe across kernel-instances (on the |
| same or different devices) is enforced at a synchronization point.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_pipe_object_queries">5.4.2. Pipe Object Queries</h4> |
| <div class="paragraph"> |
| <p>To get information that is common to all memory objects, use the |
| <strong>clGetMemObjectInfo</strong> function described in <a href="#memory-object-queries">Memory |
| Object Queries</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To get information specific to a pipe object created with <strong>clCreatePipe</strong>, |
| use the following function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetPipeInfo(cl_mem pipe, |
| cl_pipe_info param_name, |
| size_t param_value_size, |
| <span class="directive">void</span> *param_value, |
| size_t *param_value_size_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><em>pipe</em> specifies the pipe object being queried.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_name</em> specifies the information to query. |
| The list of supported <em>param_name</em> types and the information returned in |
| <em>param_value</em> by <strong>clGetPipeInfo</strong> is described in the <a href="#pipe-info-table">Pipe |
| Object Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value</em> is a pointer to memory where the appropriate result being |
| queried is returned. |
| If <em>param_value</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to |
| by <em>param_value</em>. |
| This size must be ≥ size of return type as described in the |
| <a href="#pipe-info-table">Pipe Object Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size_ret</em> returns the actual size in bytes of data being |
| queried by <em>param_name</em>. |
| If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clGetPipeInfo</strong> returns CL_SUCCESS if the function is executed successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes |
| specified by <em>param_value_size</em> is < size of return type as described in |
| the <a href="#pipe-info-table">Pipe Object Queries</a> table and <em>param_value</em> is |
| not <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>pipe</em> is a not a valid pipe object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <table id="pipe-info-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 20. List of supported param_names by <strong>clGetPipeInfo</strong></caption> |
| <colgroup> |
| <col style="width: 34%;"> |
| <col style="width: 33%;"> |
| <col style="width: 33%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_pipe_info</strong></th> |
| <th class="tableblock halign-left valign-top">Return type</th> |
| <th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PIPE_PACKET_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return pipe packet size specified when <em>pipe</em> is created with |
| <strong>clCreatePipe</strong>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PIPE_MAX_PACKETS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return max. number of packets specified when <em>pipe</em> is created with |
| <strong>clCreatePipe</strong>.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_querying_unmapping_migrating_retaining_and_releasing_memory_objects">5.5. Querying, Unmapping, Migrating, Retaining and Releasing Memory Objects</h3> |
| <div class="sect3"> |
| <h4 id="_retaining_and_releasing_memory_objects">5.5.1. Retaining and Releasing Memory Objects</h4> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clRetainMemObject(cl_mem memobj)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>increments the <em>memobj</em> reference count. |
| <strong>clRetainMemObject</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>memobj</em> is not a valid memory object (buffer |
| or image object).</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreateBuffer</strong>, <strong>clCreateSubBuffer</strong>, <strong>clCreateImage</strong> and <strong>clCreatePipe</strong> |
| perform an implicit retain.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clReleaseMemObject(cl_mem memobj)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>decrements the <em>memobj</em> reference count. |
| <strong>clReleaseMemObject</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>memobj</em> is not a valid memory object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>After the <em>memobj</em> reference count becomes zero and commands queued for |
| execution on a command-queue(s) that use <em>memobj</em> have finished, the memory |
| object is deleted. |
| If <em>memobj</em> is a buffer object, <em>memobj</em> cannot be deleted until all |
| sub-buffer objects associated with <em>memobj</em> are deleted. |
| Using this function to release a reference that was not obtained by creating |
| the object or by calling <strong>clRetainMemObject</strong> causes undefined behavior.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clSetMemObjectDestructorCallback |
| (cl_mem memobj, |
| <span class="directive">void</span> (CL_CALLBACK *pfn_notify)(cl_mem memobj,<span class="directive">void</span> *user_data), |
| <span class="directive">void</span> *user_data)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>registers a user callback function with a memory object. |
| Each call to <strong>clSetMemObjectDestructorCallback</strong> registers the specified user |
| callback function on a callback stack associated with <em>memobj</em>. |
| The registered user callback functions are called in the reverse order in |
| which they were registered. |
| The user callback functions are called and then the memory objects resources |
| are freed and the memory object is deleted. |
| This provides a mechanism for the application (and libraries) using <em>memobj</em> |
| to be notified when the memory referenced by <em>host_ptr</em>, specified when the |
| memory object is created and used as the storage bits for the memory object, |
| can be reused or freed.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>memobj</em> is a valid memory object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>pfn_notify</em> is the callback function that can be registered by the |
| application. |
| This callback function may be called asynchronously by the OpenCL |
| implementation. |
| It is the applications responsibility to ensure that the callback function |
| is thread-safe. |
| The parameters to this callback function are:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><em>memobj</em> is the memory object being deleted. |
| When the user callback is called by the implementation, this memory |
| object is not longer valid. |
| <em>memobj</em> is only provided for reference purposes.</p> |
| </li> |
| <li> |
| <p><em>user_data</em> is a pointer to user supplied data.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p><em>user_data</em> will be passed as the <em>user_data</em> argument when <em>pfn_notify</em> is |
| called. |
| <em>user_data</em> can be <code>NULL</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clSetMemObjectDestructorCallback</strong> returns CL_SUCCESS if the function is |
| executed successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>memobj</em> is not a valid memory object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>pfn_notify</em> is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>When the user callback function is called by the implementation, the |
| contents of the memory region pointed to by <em>host_ptr</em> (if the memory object |
| is created with CL_MEM_USE_HOST_PTR) are undefined. |
| The callback function is typically used by the application to either free or |
| reuse the memory region pointed to by <em>host_ptr</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The behavior of calling expensive system routines, OpenCL API calls to |
| create contexts or command-queues, or blocking OpenCL operations from the |
| following list below, in a callback is undefined.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>clFinish</strong>,</p> |
| </li> |
| <li> |
| <p><strong>clWaitForEvents</strong>,</p> |
| </li> |
| <li> |
| <p>blocking calls to <strong>clEnqueueReadBuffer</strong>, <strong>clEnqueueReadBufferRect</strong>, |
| <strong>clEnqueueWriteBuffer</strong>, <strong>clEnqueueWriteBufferRect</strong>,</p> |
| </li> |
| <li> |
| <p>blocking calls to <strong>clEnqueueReadImage</strong> and <strong>clEnqueueWriteImage</strong>,</p> |
| </li> |
| <li> |
| <p>blocking calls to <strong>clEnqueueMapBuffer</strong>, <strong>clEnqueueMapImage</strong>,</p> |
| </li> |
| <li> |
| <p>blocking calls to <strong>clBuildProgram</strong>, <strong>clCompileProgram</strong> or |
| <strong>clLinkProgram</strong></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>If an application needs to wait for completion of a routine from the above |
| list in a callback, please use the non-blocking form of the function, and |
| assign a completion callback to it to do the remainder of your work. |
| Note that when a callback (or other code) enqueues commands to a |
| command-queue, the commands are not required to begin execution until the |
| queue is flushed. |
| In standard usage, blocking enqueue calls serve this role by implicitly |
| flushing the queue. |
| Since blocking calls are not permitted in callbacks, those callbacks that |
| enqueue commands on a command queue should either call <strong>clFlush</strong> on the |
| queue before returning or arrange for <strong>clFlush</strong> to be called later on |
| another thread.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The user callback function may not call OpenCL APIs with the memory object |
| for which the callback function is invoked and for such cases the behavior |
| of OpenCL APIs is considered to be undefined.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="unmapping-mapped-memory">5.5.2. Unmapping Mapped Memory Objects</h4> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueUnmapMemObject(cl_command_queue command_queue, |
| cl_mem memobj, |
| <span class="directive">void</span> *mapped_ptr, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a command to unmap a previously mapped region of a memory object. |
| Reads or writes from the host using the pointer returned by |
| <strong>clEnqueueMapBuffer</strong> or <strong>clEnqueueMapImage</strong> are considered to be complete.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> must be a valid host command-queue.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>memobj</em> is a valid memory (buffer or image) object. |
| The OpenCL context associated with <em>command_queue</em> and <em>memobj</em> must be the |
| same.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>mapped_ptr</em> is the host address returned by a previous call to |
| <strong>clEnqueueMapBuffer</strong>, or <strong>clEnqueueMapImage</strong> for <em>memobj</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before <strong>clEnqueueUnmapMemObject</strong> can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then <strong>clEnqueueUnmapMemObject</strong> does not wait |
| on any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular command and |
| can be used to query or queue a wait for this particular command to |
| complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| <strong>clEnqueueBarrierWithWaitList</strong> can be used instead. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueUnmapMemObject</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>memobj</em> is not a valid memory object or is a |
| pipe object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>mapped_ptr</em> is not a valid pointer returned by |
| <strong>clEnqueueMapBuffer</strong> or <strong>clEnqueueMapImage</strong> for <em>memobj</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or if <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and |
| <em>memobj</em> are not the same or if the context associated with |
| <em>command_queue</em> and events in <em>event_wait_list</em> are not the same.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueMapBuffer</strong> and <strong>clEnqueueMapImage</strong> increment the mapped count of |
| the memory object. |
| The initial mapped count value of the memory object is zero. |
| Multiple calls to <strong>clEnqueueMapBuffer</strong>, or <strong>clEnqueueMapImage</strong> on the same |
| memory object will increment this mapped count by appropriate number of |
| calls. |
| <strong>clEnqueueUnmapMemObject</strong> decrements the mapped count of the memory object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueMapBuffer</strong>, and <strong>clEnqueueMapImage</strong> act as synchronization points |
| for a region of the buffer object being mapped.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="accessing-mapped-regions">5.5.3. Accessing mapped regions of a memory object</h4> |
| <div class="paragraph"> |
| <p>This section describes the behavior of OpenCL commands that access mapped |
| regions of a memory object.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The contents of the region of a memory object and associated memory objects |
| (sub-buffer objects or 1D image buffer objects that overlap this region) |
| mapped for writing (i.e. CL_MAP_WRITE or CL_MAP_WRITE_INVALIDATE_REGION is |
| set in <em>map_flags</em> argument to <strong>clEnqueueMapBuffer</strong>, or <strong>clEnqueueMapImage</strong>) |
| are considered to be undefined until this region is unmapped.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Multiple commands in command-queues can map a region or overlapping regions |
| of a memory object and associated memory objects (sub-buffer objects or 1D |
| image buffer objects that overlap this region) for reading (i.e. <em>map_flags</em> |
| = CL_MAP_READ). |
| The contents of the regions of a memory object mapped for reading can also |
| be read by kernels and other OpenCL commands (such as <strong>clEnqueueCopyBuffer</strong>) |
| executing on a device(s).</p> |
| </div> |
| <div class="paragraph"> |
| <p>Mapping (and unmapping) overlapped regions in a memory object and/or |
| associated memory objects (sub-buffer objects or 1D image buffer objects |
| that overlap this region) for writing is an error and will result in |
| CL_INVALID_OPERATION error returned by <strong>clEnqueueMapBuffer</strong>, or |
| <strong>clEnqueueMapImage</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If a memory object is currently mapped for writing, the application must |
| ensure that the memory object is unmapped before any enqueued kernels or |
| commands that read from or write to this memory object or any of its |
| associated memory objects (sub-buffer or 1D image buffer objects) or its |
| parent object (if the memory object is a sub-buffer or 1D image buffer |
| object) begin execution; otherwise the behavior is undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If a memory object is currently mapped for reading, the application must |
| ensure that the memory object is unmapped before any enqueued kernels or |
| commands that write to this memory object or any of its associated memory |
| objects (sub-buffer or 1D image buffer objects) or its parent object (if the |
| memory object is a sub-buffer or 1D image buffer object) begin execution; |
| otherwise the behavior is undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A memory object is considered as mapped if there are one or more active |
| mappings for the memory object irrespective of whether the mapped regions |
| span the entire memory object.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Accessing the contents of the memory region referred to by the mapped |
| pointer that has been unmapped is undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The mapped pointer returned by <strong>clEnqueueMapBuffer</strong> or <strong>clEnqueueMapImage</strong> |
| can be used as <em>ptr</em> argument value to <strong>clEnqueue{Read\|Write}Buffer</strong>, |
| <strong>clEnqeue{Read\|Write}BufferRect</strong>, <strong>clEnqueue{Read\|Write}Image</strong> provided |
| the rules described above are adhered to.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_migrating_memory_objects">5.5.4. Migrating Memory Objects</h4> |
| <div class="paragraph"> |
| <p>This section describes a mechanism for assigning which device an OpenCL |
| memory object resides. |
| A user may wish to have more explicit control over the location of their |
| memory objects on creation. |
| This could be used to:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Ensure that an object is allocated on a specific device prior to usage.</p> |
| </li> |
| <li> |
| <p>Preemptively migrate an object from one device to another.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueMigrateMemObjects(cl_command_queue command_queue, |
| cl_uint num_mem_objects, |
| <span class="directive">const</span> cl_mem *mem_objects, |
| cl_mem_migration_flags flags, |
| cl_uint num_events_in_wait_list |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a command to indicate which device a set of memory objects should |
| be associated with. |
| Typically, memory objects are implicitly migrated to a device for which |
| enqueued commands, using the memory object, are targeted. |
| <strong>clEnqueueMigrateMemObjects</strong> allows this migration to be explicitly |
| performed ahead of the dependent commands. |
| This allows a user to preemptively change the association of a memory |
| object, through regular command queue scheduling, in order to prepare for |
| another upcoming command. |
| This also permits an application to overlap the placement of memory objects |
| with other unrelated operations before these memory objects are needed |
| potentially hiding transfer latencies. |
| Once the event, returned from <strong>clEnqueueMigrateMemObjects</strong>, has been marked |
| CL_COMPLETE the memory objects specified in <em>mem_objects</em> have been |
| successfully migrated to the device associated with <em>command_queue</em>. |
| The migrated memory object shall remain resident on the device until another |
| command is enqueued that either implicitly or explicitly migrates it away.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueMigrateMemObjects</strong> can also be used to direct the initial |
| placement of a memory object, after creation, possibly avoiding the initial |
| overhead of instantiating the object on the first enqueued command to use |
| it.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The user is responsible for managing the event dependencies, associated with |
| this command, in order to avoid overlapping access to memory objects. |
| Improperly specified event dependencies passed to |
| <strong>clEnqueueMigrateMemObjects</strong> could result in undefined results.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> is a valid host command-queue. |
| The specified set of memory objects in <em>mem_objects</em> will be migrated to the |
| OpenCL device associated with <em>command_queue</em> or to the host if the |
| CL_MIGRATE_MEM_OBJECT_HOST has been specified.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>num_mem_objects</em> is the number of memory objects specified in |
| <em>mem_objects</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>mem_objects</em> is a pointer to a list of memory objects.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>flags</em> is a bit-field that is used to specify migration options. |
| The <a href="#migration-flags-table">Memory Migration Flags</a> describes the possible |
| values for flags.</p> |
| </div> |
| <table id="migration-flags-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 21. Supported values for cl_mem_migration_flags</caption> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_mem_migration flags</strong></th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MIGRATE_MEM_OBJECT_HOST</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag indicates that the specified set of memory objects are to be |
| migrated to the host, regardless of the target command-queue.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag indicates that the contents of the set of memory objects are |
| undefined after migration. |
| The specified set of memory objects are migrated to the device |
| associated with <em>command_queue</em> without incurring the overhead of |
| migrating their contents.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait |
| on any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular command and |
| can be used to query or queue a wait for this particular command to |
| complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueMigrateMemObjects</strong> return CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em> and |
| memory objects in <em>mem_objects</em> are not the same or if the context |
| associated with <em>command_queue</em> and events in <em>event_wait_list</em> are not |
| the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if any of the memory objects in <em>mem_objects</em> is |
| not a valid memory object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>num_mem_objects</em> is zero or if <em>mem_objects</em> is |
| <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>flags</em> is not 0 or is not any of the values |
| described in the table above.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for the specified set of memory objects in <em>mem_objects</em>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="memory-object-queries">5.5.5. Memory Object Queries</h4> |
| <div class="paragraph"> |
| <p>To get information that is common to all memory objects (buffer and image |
| objects), use the following function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetMemObjectInfo(cl_mem memobj, |
| cl_mem_info param_name, |
| size_t param_value_size, |
| <span class="directive">void</span> *param_value, |
| size_t *param_value_size_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><em>memobj</em> specifies the memory object being queried.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_name</em> specifies the information to query. |
| The list of supported <em>param_name</em> types and the information returned in |
| <em>param_value</em> by <strong>clGetMemObjectInfo</strong> is described in the |
| <a href="#mem-info-table">Memory Object Info</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value</em> is a pointer to memory where the appropriate result being |
| queried is returned. |
| If <em>param_value</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to |
| by <em>param_value</em>. |
| This size must be ≥ size of return type as described in the |
| <a href="#mem-info-table">Memory Object Info</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size_ret</em> returns the actual size in bytes of data being |
| queried by <em>param_name</em>. |
| If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clGetMemObjectInfo</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes |
| specified by <em>param_value_size</em> is < size of return type as described in |
| the <a href="#mem-info-table">Memory Object Info</a> table and <em>param_value</em> is not |
| <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if <em>memobj</em> is a not a valid memory object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <table id="mem-info-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 22. List of supported param_names by <strong>clGetMemObjectInfo</strong></caption> |
| <colgroup> |
| <col style="width: 34%;"> |
| <col style="width: 33%;"> |
| <col style="width: 33%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_mem_info</strong></th> |
| <th class="tableblock halign-left valign-top">Return type</th> |
| <th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_TYPE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_mem_object_type</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns one of the following values:</p> |
| <p class="tableblock"> CL_MEM_OBJECT_BUFFER if <em>memobj</em> is created with <strong>clCreateBuffer</strong> or |
| <strong>clCreateSubBuffer</strong>.</p> |
| <p class="tableblock"> cl_image_desc.image_type argument value if <em>memobj</em> is created with |
| <strong>clCreateImage</strong>.</p> |
| <p class="tableblock"> CL_MEM_OBJECT_PIPE if <em>memobj</em> is created with <strong>clCreatePipe</strong>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_FLAGS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_mem_flags</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the flags argument value specified when <em>memobj</em> is created |
| with <strong>clCreateBuffer</strong>,<br> |
| <strong>clCreateSubBuffer</strong>,<br> |
| <strong>clCreateImage</strong> or<br> |
| <strong>clCreatePipe</strong>.</p> |
| <p class="tableblock"> If <em>memobj</em> is a sub-buffer the memory access qualifiers inherited |
| from parent buffer is also returned.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return actual size of the data store associated with <em>memobj</em> in |
| bytes.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_HOST_PTR</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">void *</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">If <em>memobj</em> is created with <strong>clCreateBuffer</strong> or <strong>clCreateImage</strong> and |
| CL_MEM_USE_HOST_PTR is specified in mem_flags, return the host_ptr |
| argument value specified when <em>memobj</em> is created. |
| Otherwise a <code>NULL</code> value is returned.</p> |
| <p class="tableblock"> If <em>memobj</em> is created with <strong>clCreateSubBuffer</strong>, return the host_ptr |
| + origin value specified when <em>memobj</em> is created. |
| host_ptr is the argument value specified to <strong>clCreateBuffer</strong> and |
| CL_MEM_USE_HOST_PTR is specified in mem_flags for memory object from |
| which <em>memobj</em> is created. |
| Otherwise a <code>NULL</code> value is returned.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_MAP_COUNT</strong><sup>11</sup></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Map count.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_REFERENCE_COUNT</strong><sup>12</sup></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return <em>memobj</em> reference count.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_CONTEXT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_context</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return context specified when memory object is created. |
| If <em>memobj</em> is created using <strong>clCreateSubBuffer</strong>, the context |
| associated with the memory object specified as the <em>buffer</em> argument |
| to <strong>clCreateSubBuffer</strong> is returned.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_ASSOCIATED_MEMOBJECT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_mem</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return memory object from which <em>memobj</em> is created. |
| This returns the memory object specified as buffer argument to |
| <strong>clCreateSubBuffer</strong> if <em>memobj</em> is a subbuffer object created using |
| <strong>clCreateSubBuffer</strong>.</p> |
| <p class="tableblock"> This returns the mem_object specified in cl_image_desc if <em>memobj</em> |
| is an image object.</p> |
| <p class="tableblock"> Otherwise a <code>NULL</code> value is returned.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_OFFSET</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return offset if <em>memobj</em> is a sub-buffer object created using |
| <strong>clCreateSubBuffer</strong>.</p> |
| <p class="tableblock"> This return 0 if <em>memobj</em> is not a subbuffer object.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_USES_SVM_POINTER</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return CL_TRUE if <em>memobj</em> is a buffer object that was created with |
| CL_MEM_USE_HOST_PTR or is a sub-buffer object of a buffer object |
| that was created with CL_MEM_USE_HOST_PTR and the <em>host_ptr</em> |
| specified when the buffer object was created is a SVM pointer; |
| otherwise returns CL_FALSE.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">11</dt> |
| <dd> |
| <p>The map count returned should be considered immediately stale. |
| It is unsuitable for general use in applications. |
| This feature is provided for debugging.</p> |
| </dd> |
| <dt class="hdlist1">12</dt> |
| <dd> |
| <p>The reference count returned should be considered immediately stale. |
| It is unsuitable for general use in applications. |
| This feature is provided for identifying memory leaks.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_shared_virtual_memory">5.6. Shared Virtual Memory</h3> |
| <div class="paragraph"> |
| <p>OpenCL 2.2 adds support for shared virtual memory (a.k.a. |
| SVM). |
| SVM allows the host and kernels executing on devices to directly share |
| complex, pointer-containing data structures such as trees and linked lists. |
| It also eliminates the need to marshal data between the host and devices. |
| As a result, SVM substantially simplifies OpenCL programming and may improve |
| performance.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="_svm_sharing_granularity_coarse_and_fine_grained_sharing">5.6.1. SVM sharing granularity: coarse- and fine- grained sharing</h4> |
| <div class="paragraph"> |
| <p>OpenCL maintains memory consistency in a coarse-grained fashion in regions |
| of buffers. |
| We call this coarse-grained sharing. |
| Many platforms such as those with integrated CPU-GPU processors and ones |
| using the SVM-related PCI-SIG IOMMU services can do better, and can support |
| sharing at a granularity smaller than a buffer. |
| We call this fine-grained sharing. |
| OpenCL 2.0 requires that the host and all OpenCL 2.2 devices support |
| coarse-grained sharing at a minimum.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Coarse-grained sharing: Coarse-grain sharing may be used for memory and |
| virtual pointer sharing between multiple devices as well as between the |
| host and one or more devices. |
| The shared memory region is a memory buffer allocated using |
| <strong>clSVMAlloc</strong>. |
| Memory consistency is guaranteed at synchronization points and the host |
| can use calls to <strong>clEnqueueSVMMap</strong> and <strong>clEnqueueSVMUnmap</strong> or create a |
| cl_mem buffer object using the SVM pointer and use OpenCLs existing host |
| API functions <strong>clEnqueueMapBuffer</strong> and <strong>clEnqueueUnmapMemObject</strong> to |
| update regions of the buffer. |
| What coarse-grain buffer SVM adds to OpenCLs earlier buffer support are |
| the ability to share virtual memory pointers and a guarantee that |
| concurrent access to the same memory allocation from multiple kernels on |
| a single device is valid. |
| The coarse-grain buffer SVM provides a memory consistency model similar |
| to the global memory consistency model described in <em>sections 3.3.1</em> and |
| <em>3.4.3</em> of the OpenCL 1.2 specification. |
| This memory consistency applies to the regions of buffers being shared |
| in a coarse-grained fashion. |
| It is enforced at the synchronization points between commands enqueued |
| to command queues in a single context with the additional consideration |
| that multiple kernels concurrently running on the same device may safely |
| share the data.</p> |
| </li> |
| <li> |
| <p>Fine-grained sharing: Shared virtual memory where memory consistency is |
| maintained at a granularity smaller than a buffer. |
| How fine-grained SVM is used depends on whether the device supports SVM |
| atomic operations.</p> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>If SVM atomic operations are supported, they provide memory consistency |
| for loads and stores by the host and kernels executing on devices |
| supporting SVM. |
| This means that the host and devices can concurrently read and update |
| the same memory. |
| The consistency provided by SVM atomics is in addition to the |
| consistency provided at synchronization points. |
| There is no need for explicit calls to <strong>clEnqueueSVMMap</strong> and |
| <strong>clEnqueueSVMUnmap</strong> or <strong>clEnqueueMapBuffer</strong> and |
| <strong>clEnqueueUnmapMemObject</strong> on a cl_mem buffer object created using the |
| SVM pointer.</p> |
| </li> |
| <li> |
| <p>If SVM atomic operations are not supported, the host and devices can |
| concurrently read the same memory locations and can concurrently update |
| non-overlapping memory regions, but attempts to update the same memory |
| locations are undefined. |
| Memory consistency is guaranteed at synchronization points without the |
| need for explicit calls to to <strong>clEnqueueSVMMap</strong> and <strong>clEnqueueSVMUnmap</strong> |
| or <strong>clEnqueueMapBuffer</strong> and <strong>clEnqueueUnmapMemObject</strong> on a cl_mem |
| buffer object created using the SVM pointer.</p> |
| </li> |
| </ul> |
| </div> |
| </li> |
| <li> |
| <p>There are two kinds of fine-grain sharing support. |
| Devices may support either fine-grain buffer sharing or fine-grain |
| system sharing.</p> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Fine-grain buffer sharing provides fine-grain SVM only within buffers |
| and is an extension of coarse-grain sharing. |
| To support fine-grain buffer sharing in an OpenCL context, all devices |
| in the context must support CL_DEVICE_SVM_FINE_GRAIN_BUFFER.</p> |
| </li> |
| <li> |
| <p>Fine-grain system sharing enables fine-grain sharing of the hosts |
| entire virtual memory, including memory regions allocated by the system |
| <strong>malloc</strong> API. |
| OpenCL buffer objects are unnecessary and programmers can pass pointers |
| allocated using <strong>malloc</strong> to OpenCL kernels.</p> |
| </li> |
| </ul> |
| </div> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>As an illustration of fine-grain SVM using SVM atomic operations to maintain |
| memory consistency, consider the following example. |
| The host and a set of devices can simultaneously access and update a shared |
| work-queue data structure holding work-items to be done. |
| The host can use atomic operations to insert new work-items into the queue |
| at the same time as the devices using similar atomic operations to remove |
| work-items for processing.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is the programmers responsibility to ensure that no host code or |
| executing kernels attempt to access a shared memory region after that memory |
| is freed. |
| We require the SVM implementation to work with either 32- or 64- bit host |
| applications subject to the following requirement: the address space size |
| must be the same for the host and all OpenCL devices in the context.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c"><span class="directive">void</span>* clSVMAlloc(cl_context context, |
| cl_svm_mem_flags flags, |
| size_t size, |
| cl_uint alignment)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>allocates a shared virtual memory buffer (referred to as a SVM buffer) that |
| can be shared by the host and all devices in an OpenCL context that support |
| shared virtual memory.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>context</em> is a valid OpenCL context used to create the SVM buffer.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>flags</em> is a bit-field that is used to specify allocation and usage |
| information. |
| The <a href="#svm-flags-table">SVM Memory Flags</a> table describes the possible values |
| for <em>flags</em>.</p> |
| </div> |
| <table id="svm-flags-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 23. List of supported cl_svm_mem_flags_ values</caption> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_svm_mem_flags</strong></th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_READ_WRITE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the SVM buffer will be read and written by a |
| kernel. |
| This is the default.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_WRITE_ONLY</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the SVM buffer will be written but not read by |
| a kernel.</p> |
| <p class="tableblock"> Reading from a SVM buffer created with CL_MEM_WRITE_ONLY inside a kernel |
| is undefined.</p> |
| <p class="tableblock"> CL_MEM_READ_WRITE and CL_MEM_WRITE_ONLY are mutually exclusive.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_READ_ONLY</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the SVM buffer object is a read-only memory |
| object when used inside a kernel.</p> |
| <p class="tableblock"> Writing to a SVM buffer created with CL_MEM_READ_ONLY inside a kernel is |
| undefined.</p> |
| <p class="tableblock"> CL_MEM_READ_WRITE or CL_MEM_WRITE_ONLY and CL_MEM_READ_ONLY are mutually |
| exclusive.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_SVM_FINE_GRAIN_BUFFER</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This specifies that the application wants the OpenCL implementation to |
| do a fine-grained allocation.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_SVM_ATOMICS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag is valid only if CL_MEM_SVM_FINE_GRAIN_BUFFER is specified in |
| flags. |
| It is used to indicate that SVM atomic operations can control visibility |
| of memory accesses in this SVM buffer.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>If CL_MEM_SVM_FINE_GRAIN_BUFFER is not specified, the buffer can be created |
| as a coarse grained SVM allocation. |
| Similarly, if CL_MEM_SVM_ATOMICS is not specified, the buffer can be created |
| without support for SVM atomic operations (refer to an OpenCL kernel |
| language specifications).</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>size</em> is the size in bytes of the SVM buffer to be allocated.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>alignment</em> is the minimum alignment in bytes that is required for the newly |
| created buffers memory region. |
| It must be a power of two up to the largest data type supported by the |
| OpenCL device. |
| For the full profile, the largest data type is long16. |
| For the embedded profile, it is long16 if the device supports 64-bit |
| integers; otherwise it is int16. |
| If alignment is 0, a default alignment will be used that is equal to the |
| size of largest data type supported by the OpenCL implementation.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clSVMAlloc</strong> returns a valid non-<code>NULL</code> shared virtual memory address if the |
| SVM buffer is successfully allocated. |
| Otherwise, like <strong>malloc</strong>, it returns a <code>NULL</code> pointer value. |
| <strong>clSVMAlloc</strong> will fail if</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><em>context</em> is not a valid context.</p> |
| </li> |
| <li> |
| <p><em>flags</em> does not contain CL_MEM_SVM_FINE_GRAIN_BUFFER but does contain |
| CL_MEM_SVM_ATOMICS.</p> |
| </li> |
| <li> |
| <p>Values specified in <em>flags</em> do not follow rules described for supported |
| values in the <a href="#svm-flags-table">SVM Memory Flags</a> table.</p> |
| </li> |
| <li> |
| <p>CL_MEM_SVM_FINE_GRAIN_BUFFER or CL_MEM_SVM_ATOMICS is specified in |
| <em>flags</em> and these are not supported by at least one device in <em>context</em>.</p> |
| </li> |
| <li> |
| <p>The values specified in <em>flags</em> are not valid, i.e. don’t match those |
| defined in the <a href="#svm-flags-table">SVM Memory Flags</a> table.</p> |
| </li> |
| <li> |
| <p><em>size</em> is 0 or > CL_DEVICE_MAX_MEM_ALLOC_SIZE value for any device in |
| <em>context</em>.</p> |
| </li> |
| <li> |
| <p><em>alignment</em> is not a power of two or the OpenCL implementation cannot |
| support the specified alignment for at least one device in <em>context</em>.</p> |
| </li> |
| <li> |
| <p>There was a failure to allocate resources.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Calling <strong>clSVMAlloc</strong> does not itself provide consistency for the shared |
| memory region. |
| When the host cannot use the SVM atomic operations, it must rely on OpenCLs |
| guaranteed memory consistency at synchronization points.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For SVM to be used efficiently, the host and any devices sharing a buffer |
| containing virtual memory pointers should have the same endianness. |
| If the context passed to <strong>clSVMAlloc</strong> has devices with mixed endianness and |
| the OpenCL implementation is unable to implement SVM because of that mixed |
| endianness, <strong>clSVMAlloc</strong> will fail and return <code>NULL</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Although SVM is generally not supported for image objects, <strong>clCreateImage</strong> |
| may create an image from a buffer (a 1D image from a buffer or a 2D image |
| from buffer) if the buffer specified in its image description parameter is a |
| SVM buffer. |
| Such images have a linear memory representation so their memory can be |
| shared using SVM. |
| However, fine grained sharing and atomics are not supported for image reads |
| and writes in a kernel.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c"><span class="directive">void</span> clSVMFree(cl_context context, |
| <span class="directive">void</span> *svm_pointer)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>frees a shared virtual memory buffer allocated using <strong>clSVMAlloc</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>context</em> is a valid OpenCL context used to create the SVM buffer.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>svm_pointer</em> must be the value returned by a call to <strong>clSVMAlloc</strong>. |
| If a <code>NULL</code> pointer is passed in <em>svm_pointer</em>, no action occurs.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Note that <strong>clSVMFree</strong> does not wait for previously enqueued commands that |
| may be using <em>svm_pointer</em> to finish before freeing <em>svm_pointer</em>. |
| It is the responsibility of the application to make sure that enqueued |
| commands that use <em>svm_pointer</em> have finished before freeing <em>svm_pointer</em>. |
| This can be done by enqueuing a blocking operation such as <strong>clFinish</strong>, |
| <strong>clWaitForEvents</strong>, <strong>clEnqueueReadBuffer</strong> or by registering a callback with |
| the events associated with enqueued commands and when the last enqueued |
| command has finished freeing <em>svm_pointer</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The behavior of using <em>svm_pointer</em> after it has been freed is undefined. |
| In addition, if a buffer object is created using <strong>clCreateBuffer</strong> with |
| <em>svm_pointer</em>, the buffer object must first be released before the |
| <em>svm_pointer</em> is freed.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>clEnqueueSVMFree</strong> API can also be used to enqueue a callback to free |
| the shared virtual memory buffer allocated using <strong>clSVMAlloc</strong> or a shared |
| system memory pointer.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueSVMFree(cl_command_queue command_queue, |
| cl_uint num_svm_pointers, |
| <span class="directive">void</span> *svm_pointers[], |
| <span class="directive">void</span> (CL_CALLBACK *pfn_free_func) |
| (cl_command_queue queue, |
| cl_uint num_svm_pointers, |
| <span class="directive">void</span> *svm_pointers[], |
| <span class="directive">void</span> *user_data), |
| <span class="directive">void</span> *user_data, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a command to free the shared virtual memory allocated using |
| <strong>clSVMAlloc</strong> or a shared system memory pointer.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> is a valid host command-queue.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>svm_pointers</em> and <em>num_svm_pointers</em> specify shared virtual memory pointers |
| to be freed. |
| Each pointer in <em>svm_pointers</em> that was allocated using <strong>clSVMAlloc</strong> must |
| have been allocated from the same context from which <em>command_queue</em> was |
| created. |
| The memory associated with <em>svm_pointers</em> can be reused or freed after the |
| function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>pfn_free_func</em> specifies the callback function to be called to free the SVM |
| pointers. |
| <em>pfn_free_func</em> takes four arguments: <em>queue</em> which is the command queue in |
| which <strong>clEnqueueSVMFree</strong> was enqueued, the count and list of SVM pointers to |
| free and <em>user_data</em> which is a pointer to user specified data. |
| If <em>pfn_free_func</em> is <code>NULL</code>, all pointers specified in <em>svm_pointers</em> must |
| be allocated using <strong>clSVMAlloc</strong> and the OpenCL implementation will free |
| these SVM pointers. |
| <em>pfn_free_func</em> must be a valid callback function if any SVM pointer to be |
| freed is a shared system memory pointer i.e. not allocated using |
| <strong>clSVMAlloc</strong>. |
| If <em>pfn_free_func</em> is a valid callback function, the OpenCL implementation |
| will call <em>pfn_free_func</em> to free all the SVM pointers specified in |
| <em>svm_pointers</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>user_data</em> will be passed as the <em>user_data</em> argument when <em>pfn_free_func</em> |
| is called. |
| <em>user_data</em> can be <code>NULL</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before <strong>clEnqueueSVMFree</strong> can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then <strong>clEnqueueSVMFree</strong> does not wait on any |
| event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular command and |
| can be used to query or queue a wait for this particular command to |
| complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueSVMFree</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>num_svm_pointers</em> is 0 and <em>svm_pointers</em> is |
| non-<code>NULL</code>, <em>or</em> if <em>svm_pointers</em> is <code>NULL</code> and <em>num_svm_pointers</em> is |
| not 0.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The following function enqueues a command to do a memcpy operation.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueSVMMemcpy(cl_command_queue command_queue, |
| cl_bool blocking_copy, |
| <span class="directive">void</span> *dst_ptr, |
| <span class="directive">const</span> <span class="directive">void</span> *src_ptr, |
| size_t size, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> refers to the host command-queue in which the read / write |
| command will be queued. |
| If either <em>dst_ptr</em> or <em>src_ptr</em> is allocated using <strong>clSVMAlloc</strong> then the |
| OpenCL context allocated against must match that of <em>command_queue</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>blocking_copy</em> indicates if the copy operation is <em>blocking</em> or |
| <em>non-blocking</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_copy</em> is CL_TRUE i.e. the copy command is blocking, |
| <strong>clEnqueueSVMMemcpy</strong> does not return until the buffer data has been copied |
| into memory pointed to by <em>dst_ptr</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_copy</em> is CL_FALSE i.e. the copy command is non-blocking, |
| <strong>clEnqueueSVMMemcpy</strong> queues a non-blocking copy command and returns. |
| The contents of the buffer that <em>dst_ptr</em> points to cannot be used until the |
| copy command has completed. |
| The <em>event</em> argument returns an event object which can be used to query the |
| execution status of the read command. |
| When the copy command has completed, the contents of the buffer that |
| <em>dst_ptr</em> points to can be used by the application.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>size</em> is the size in bytes of data being copied.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>dst_ptr</em> is the pointer to a host or SVM memory allocation where data is |
| copied to.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>src_ptr</em> is the pointer to a host or SVM memory allocation where data is |
| copied from.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the memory allocation(s) containing <em>dst_ptr</em> and/or <em>src_ptr</em> are |
| allocated using <strong>clSVMAlloc</strong> and either is not allocated from the same |
| context from which <em>command_queue</em> was created the behavior is undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait |
| on any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular read / write |
| command and can be used to query or queue a wait for this particular command |
| to complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueSVMMemcpy</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em> and |
| events in <em>event_wait_list</em> are not the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the copy operation is |
| blocking and the execution status of any of the events in |
| <em>event_wait_list</em> is a negative integer value.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>dst_ptr</em> or <em>src_ptr</em> are <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_MEM_COPY_OVERLAP if the values specified for <em>dst_ptr</em>, <em>src_ptr</em> and |
| <em>size</em> result in an overlapping copy.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueSVMMemFill(cl_command_queue command_queue, |
| <span class="directive">void</span> *svm_ptr, |
| <span class="directive">const</span> <span class="directive">void</span> *pattern, |
| size_t pattern_size, |
| size_t size, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a command to fill a region in memory with a pattern of a given |
| pattern size.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> refers to the host command-queue in which the fill command |
| will be queued. |
| The OpenCL context associated with <em>command_queue</em> and SVM pointer referred |
| to by <em>svm_ptr</em> must be the same.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>svm_ptr</em> is a pointer to a memory region that will be filled with |
| <em>pattern</em>. |
| It must be aligned to <em>pattern_size</em> bytes. |
| If <em>svm_ptr</em> is allocated using <strong>clSVMAlloc</strong> then it must be allocated from |
| the same context from which <em>command_queue</em> was created. |
| Otherwise the behavior is undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>pattern</em> is a pointer to the data pattern of size <em>pattern_size</em> in bytes. |
| <em>pattern</em> will be used to fill a region in <em>buffer</em> starting at <em>svm_ptr</em> |
| and is <em>size</em> bytes in size. |
| The data pattern must be a scalar or vector integer or floating-point data |
| type supported by OpenCL as described in <a href="#scalar-data-types">Shared |
| Application Scalar Data Types</a> and <a href="#vector-data-types">Supported |
| Application Vector Data Types</a>. |
| For example, if region pointed to by <em>svm_ptr</em> is to be filled with a |
| pattern of float4 values, then <em>pattern</em> will be a pointer to a cl_float4 |
| value and <em>pattern_size</em> will be <code>sizeof(cl_float4)</code>. |
| The maximum value of <em>pattern_size</em> is the size of the largest integer or |
| floating-point vector data type supported by the OpenCL device. |
| The memory associated with <em>pattern</em> can be reused or freed after the |
| function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>size</em> is the size in bytes of region being filled starting with <em>svm_ptr</em> |
| and must be a multiple of <em>pattern_size</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait |
| on any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular command and |
| can be used to query or queue a wait for this particular command to |
| complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| <strong>clEnqueueBarrierWithWaitList</strong> can be used instead. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueSVMMemFill</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em> and |
| events in <em>event_wait_list</em> are not the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>svm_ptr</em> is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>svm_ptr</em> is not aligned to <em>pattern_size</em> bytes.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>pattern</em> is <code>NULL</code> or if <em>pattern_size</em> is 0 or if |
| <em>pattern_size</em> is not one of {1, 2, 4, 8, 16, 32, 64, 128}.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>size</em> is not a multiple of <em>pattern_size</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueSVMMap(cl_command_queue command_queue, |
| cl_bool blocking_map, |
| cl_map_flags map_flags, |
| <span class="directive">void</span> *svm_ptr, |
| size_t size, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a command that will allow the host to update a region of a SVM |
| buffer. |
| Note that since we are enqueuing a command with a SVM buffer, the region is |
| already mapped in the host address space.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> must be a valid host command-queue.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>blocking_map</em> indicates if the map operation is <em>blocking</em> or |
| <em>non-blocking</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_map</em> is CL_TRUE, <strong>clEnqueueSVMMap</strong> does not return until the |
| application can access the contents of the SVM region specified by <em>svm_ptr</em> |
| and <em>size</em> on the host.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>blocking_map</em> is CL_FALSE i.e. map operation is non-blocking, the region |
| specified by <em>svm_ptr</em> and <em>size</em> cannot be used until the map command has |
| completed. |
| The <em>event</em> argument returns an event object which can be used to query the |
| execution status of the map command. |
| When the map command is completed, the application can access the contents |
| of the region specified by <em>svm_ptr</em> and <em>size</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>map_flags</em> is a bit-field and is described in the |
| <a href="#memory-map-flags-table">Memory Map Flags</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>svm_ptr</em> and <em>size</em> are a pointer to a memory region and size in bytes that |
| will be updated by the host. |
| If <em>svm_ptr</em> is allocated using <strong>clSVMAlloc</strong> then it must be allocated from |
| the same context from which <em>command_queue</em> was created. |
| Otherwise the behavior is undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait |
| on any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular command and |
| can be used to query or queue a wait for this particular command to |
| complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| <strong>clEnqueueBarrierWithWaitList</strong> can be used instead. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueSVMMap</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and events |
| in <em>event_wait_list</em> are not the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>svm_ptr</em> is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>size</em> is 0 or if values specified in <em>map_flags</em> |
| are not valid.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the map operation is |
| blocking and the execution status of any of the events in |
| <em>event_wait_list</em> is a negative integer value.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueSVMUnmap(cl_command_queue command_queue, |
| <span class="directive">void</span> *svm_ptr, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a command to indicate that the host has completed updating the |
| region given by <em>svm_ptr</em> and which was specified in a previous call to |
| <strong>clEnqueueSVMMap</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> must be a valid host command-queue.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>svm_ptr</em> is a pointer that was specified in a previous call to |
| <strong>clEnqueueSVMMap</strong>. |
| If <em>svm_ptr</em> is allocated using <strong>clSVMAlloc</strong> then it must be allocated from |
| the same context from which <em>command_queue</em> was created. |
| Otherwise the behavior is undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before <strong>clEnqueueSVMUnmap</strong> can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then <strong>clEnqueueUnmap</strong> does not wait on any |
| event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular command and |
| can be used to query or queue a wait for this particular command to |
| complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| <strong>clEnqueueBarrierWithWaitList</strong> can be used instead. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueSVMUnmap</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and events |
| in <em>event_wait_list</em> are not the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>svm_ptr</em> is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or if <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueSVMMap</strong> and <strong>clEnqueueSVMUnmap</strong> act as synchronization points for |
| the region of the SVM buffer specified in these calls.</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="paragraph"> |
| <p>If a coarse-grained SVM buffer is currently mapped for writing, the |
| application must ensure that the SVM buffer is unmapped before any enqueued |
| kernels or commands that read from or write to this SVM buffer or any of its |
| associated cl_mem buffer objects begin execution; otherwise the behavior is |
| undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If a coarse-grained SVM buffer is currently mapped for reading, the |
| application must ensure that the SVM buffer is unmapped before any enqueued |
| kernels or commands that write to this memory object or any of its |
| associated cl_mem buffer objects begin execution; otherwise the behavior is |
| undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A SVM buffer is considered as mapped if there are one or more active |
| mappings for the SVM buffer irrespective of whether the mapped regions span |
| the entire SVM buffer.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The above note does not apply to fine-grained SVM buffers (fine-grained |
| buffers allocated using <strong>clSVMAlloc</strong> or fine-grained system allocations).</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueSVMMigrateMem(cl_command_queue command_queue, |
| cl_uint num_svm_pointers, |
| <span class="directive">const</span> <span class="directive">void</span> **svm_pointers, |
| <span class="directive">const</span> size_t *sizes, |
| cl_mem_migration_flags flags, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a command to indicate which device a set of ranges of SVM |
| allocations should be associated with. |
| Once the event returned by <strong>clEnqueueSVMMigrateMem</strong> has become CL_COMPLETE, |
| the ranges specified by svm pointers and sizes have been successfully |
| migrated to the device associated with command queue.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The user is responsible for managing the event dependencies associated with |
| this command in order to avoid overlapping access to SVM allocations. |
| Improperly specified event dependencies passed to <strong>clEnqueueSVMMigrateMem</strong> |
| could result in undefined results.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> is a valid host command queue. |
| The specified set of allocation ranges will be migrated to the OpenCL device |
| associated with <em>command_queue</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>num_svm_pointers</em> is the number of pointers in the specified <em>svm_pointers</em> |
| array, and the number of sizes in the <em>sizes</em> array, if <em>sizes</em> is not |
| <code>NULL</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>svm_pointers</em> is a pointer to an array of pointers. |
| Each pointer in this array must be within an allocation produced by a call |
| to <strong>clSVMAlloc</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>sizes</em> is an array of sizes. |
| The pair <em>svm_pointers</em>[i] and <em>sizes</em>[i] together define the starting |
| address and number of bytes in a range to be migrated. |
| <em>sizes</em> may be <code>NULL</code> indicating that every allocation containing any |
| <em>svm_pointer</em>[i] is to be migrated. |
| Also, if <em>sizes</em>[i] is zero, then the entire allocation containing |
| <em>svm_pointer</em>[i] is migrated.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>flags</em> is a bit-field that is used to specify migration options. |
| The <a href="#migration-flags-table">Memory Migration Flags</a> describes the possible |
| values for <em>flags</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait |
| on any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular command and |
| can be used to query or queue a wait for this particular command to |
| complete. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue another command |
| that waits for this command to complete. |
| If the <em>event_wait_list</em> and <em>event</em> arguments are not <code>NULL</code>, the <em>event</em> |
| argument should not refer to an element of the <em>event_wait_list</em> array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueSVMMigrateMem</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and events |
| in <em>event_wait_list</em> are not the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>num_svm_pointers</em> is zero or <em>svm_pointers</em> is |
| <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>sizes</em>[i] is non-zero range [<em>svm_pointers</em>[i], |
| <em>svm_pointers</em>[i]+<em>sizes</em>[i]) is not contained within an existing |
| <strong>clSVMAlloc</strong> allocation.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or if <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_memory_consistency_for_svm_allocations">5.6.2. Memory consistency for SVM allocations</h4> |
| <div class="paragraph"> |
| <p>To ensure memory consistency in SVM allocations, the program can rely on the |
| guaranteed memory consistency at synchronization points. |
| This consistency support already exists in OpenCL 1.x and can be used for |
| coarse-grained SVM allocations or for fine-grained buffer SVM allocations; |
| what SVM adds is the ability to share pointers between the host and all SVM |
| devices.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In addition, sub-buffers can also be used to ensure that each device gets a |
| consistent view of a SVM buffers memory when it is shared by multiple |
| devices. |
| For example, assume that two devices share a SVM pointer. |
| The host can create a cl_mem buffer object using <strong>clCreateBuffer</strong> with |
| CL_MEM_USE_HOST_PTR and <em>host_ptr</em> set to the SVM pointer and then create |
| two disjoint sub-buffers with starting virtual addresses <em>sb1_ptr</em> and |
| <em>sb2_ptr</em>. |
| These pointers (<em>sb1_ptr</em> and <em>sb2_ptr</em>) can be passed to kernels executing |
| on the two devices. |
| <strong>clEnqueueMapBuffer</strong> and <strong>clEnqueueUnmapMemObject</strong> and the existing |
| <a href="#accessing-mapped-regions">access rules for memory objects</a> ensure |
| consistency for buffer regions (<em>sb1_ptr</em> and <em>sb2_ptr</em>) read and written by |
| these kernels.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When the host and devices are able to use SVM atomic operations (i.e. |
| CL_DEVICE_SVM_ATOMICS is set in CL_DEVICE_SVM_CAPABILITIES), these atomic |
| operations can be used to provide memory consistency at a fine grain in a |
| shared memory region. |
| The effect of these operations is visible to the host and all devices with |
| which that memory is shared.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_sampler_objects">5.7. Sampler Objects</h3> |
| <div class="paragraph"> |
| <p>A sampler object describes how to sample an image when the image is read in |
| the kernel. |
| The built-in functions to read from an image in a kernel take a sampler as |
| an argument. |
| The sampler arguments to the image read function can be sampler objects |
| created using OpenCL functions and passed as argument values to the kernel |
| or can be samplers declared inside a kernel. |
| In this section we discuss how sampler objects are created using OpenCL |
| functions.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="_creating_sampler_objects">5.7.1. Creating Sampler Objects</h4> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_sampler clCreateSamplerWithProperties(cl_context context, |
| <span class="directive">const</span> cl_sampler_properties *sampler_properties, |
| cl_int *errcode_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>creates a sampler object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>context</em> must be a valid OpenCL context.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>sampler_properties</em> specifies a list of sampler property names and their |
| corresponding values. |
| Each sampler property name is immediately followed by the corresponding |
| desired value. |
| The list is terminated with 0. |
| The list of supported properties is described in the |
| <a href="#sampler-properties-table">Sampler Properties</a> table. |
| If a supported property and its value is not specified in |
| <em>sampler_properties</em>, its default value will be used. |
| <em>sampler_properties</em> can be <code>NULL</code> in which case the default values for |
| supported sampler properties will be used.</p> |
| </div> |
| <table id="sampler-properties-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 24. List of supported cl_sampler_properties values and description</caption> |
| <colgroup> |
| <col style="width: 34%;"> |
| <col style="width: 33%;"> |
| <col style="width: 33%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_sampler_properties</strong> enum</th> |
| <th class="tableblock halign-left valign-top">Property Value</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_NORMALIZED_COORDS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">A boolean value that specifies whether the image coordinates |
| specified are normalized or not.</p> |
| <p class="tableblock"> The default value (i.e. the value used if this property is not |
| specified in sampler_properties) is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_ADDRESSING_MODE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_addressing_mode</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Specifies how out-of-range image coordinates are handled when |
| reading from an image.</p> |
| <p class="tableblock"> Valid values are:</p> |
| <p class="tableblock"> CL_ADDRESS_MIRRORED_REPEAT<br> |
| CL_ADDRESS_REPEAT<br> |
| CL_ADDRESS_CLAMP_TO_EDGE<br> |
| CL_ADDRESS_CLAMP<br> |
| CL_ADDRESS_NONE</p> |
| <p class="tableblock"> The default is CL_ADDRESS_CLAMP.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_FILTER_MODE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_filter_mode</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Specifies the type of filter that must be applied when reading an |
| image. |
| Valid values are:</p> |
| <p class="tableblock"> CL_FILTER_NEAREST<br> |
| CL_FILTER_LINEAR</p> |
| <p class="tableblock"> The default value is CL_FILTER_NEAREST.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p><em>errcode_ret</em> will return an appropriate error code. |
| If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreateSamplerWithProperties</strong> returns a valid non-zero sampler object and |
| <em>errcode_ret</em> is set to CL_SUCCESS if the sampler object is created |
| successfully. |
| Otherwise, it returns a <code>NULL</code> value with one of the following error values |
| returned in <em>errcode_ret</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if the property name in <em>sampler_properties</em> is not a |
| supported property name, if the value specified for a supported property |
| name is not valid, or if the same property name is specified more than |
| once.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if images are not supported by any device |
| associated with <em>context</em> (i.e. CL_DEVICE_IMAGE_SUPPORT specified in the |
| <a href="#device-queries-table">Device Queries</a> table is CL_FALSE).</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clRetainSampler(cl_sampler sampler)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>increments the <em>sampler</em> reference count. |
| <strong>clCreateSamplerWithProperties</strong> performs an implicit retain. |
| <strong>clRetainSampler</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_SAMPLER if <em>sampler</em> is not a valid sampler object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clReleaseSampler(cl_sampler sampler)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>decrements the <em>sampler</em> reference count. |
| The sampler object is deleted after the reference count becomes zero and |
| commands queued for execution on a command-queue(s) that use <em>sampler</em> have |
| finished. |
| <strong>clReleaseSampler</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_SAMPLER if <em>sampler</em> is not a valid sampler object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Using this function to release a reference that was not obtained by creating |
| the object or by calling <strong>clRetainSampler</strong> causes undefined behavior.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_sampler_object_queries">5.7.2. Sampler Object Queries</h4> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetSamplerInfo(cl_sampler sampler, |
| cl_sampler_info param_name, |
| size_t param_value_size, |
| <span class="directive">void</span> *param_value, |
| size_t *param_value_size_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>returns information about the sampler object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>sampler</em> specifies the sampler being queried.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_name</em> specifies the information to query. |
| The list of supported <em>param_name</em> types and the information returned in |
| <em>param_value</em> by <strong>clGetSamplerInfo</strong> is described in the |
| <a href="#sampler-info-table">Sampler Object Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value</em> is a pointer to memory where the appropriate result being |
| queried is returned. |
| If <em>param_value</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to |
| by <em>param_value</em>. |
| This size must be ≥ size of return type as described in the |
| <a href="#sampler-info-table">Sampler Object Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size_ret</em> returns the actual size in bytes of data being |
| queried by <em>param_name</em>. |
| If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <table id="sampler-info-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 25. <strong>clGetSamplerInfo</strong> parameter queries</caption> |
| <colgroup> |
| <col style="width: 34%;"> |
| <col style="width: 33%;"> |
| <col style="width: 33%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_sampler_info</strong></th> |
| <th class="tableblock halign-left valign-top">Return Type</th> |
| <th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_REFERENCE_COUNT</strong><sup>13</sup></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the <em>sampler</em> reference count.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_CONTEXT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_context</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the context specified when the sampler is created.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_NORMALIZED_COORDS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the normalized coords value associated with <em>sampler</em>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_ADDRESSING_MODE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_addressing_mode</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the addressing mode value associated with <em>sampler</em>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_FILTER_MODE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_filter_mode</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the filter mode value associated with <em>sampler</em>.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">13</dt> |
| <dd> |
| <p>The reference count returned should be considered immediately stale. |
| It is unsuitable for general use in applications. |
| This feature is provided for identifying memory leaks.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clGetSamplerInfo</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes |
| specified by <em>param_value_size</em> is < size of return type as described in |
| the <a href="#sampler-info-table">Sampler Object Queries</a> table and |
| <em>param_value</em> is not <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_SAMPLER if <em>sampler</em> is a not a valid sampler object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_program_objects">5.8. Program Objects</h3> |
| <div class="paragraph"> |
| <p>An OpenCL program consists of a set of kernels that are identified as |
| functions declared with the <code>__kernel</code> qualifier in the program source. |
| OpenCL programs may also contain auxiliary functions and constant data that |
| can be used by <code>__kernel</code> functions. |
| The program executable can be generated <em>online</em> or <em>offline</em> by the OpenCL |
| compiler for the appropriate target device(s).</p> |
| </div> |
| <div class="paragraph"> |
| <p>A program object encapsulates the following information:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>An associated context.</p> |
| </li> |
| <li> |
| <p>A program source or binary.</p> |
| </li> |
| <li> |
| <p>The latest successfully built program executable, library or compiled |
| binary, the list of devices for which the program executable, library or |
| compiled binary is built, the build options used and a build log.</p> |
| </li> |
| <li> |
| <p>The number of kernel objects currently attached.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="sect3"> |
| <h4 id="_creating_program_objects">5.8.1. Creating Program Objects</h4> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_program clCreateProgramWithSource(cl_context context, |
| cl_uint count, |
| <span class="directive">const</span> <span class="predefined-type">char</span> **strings, |
| <span class="directive">const</span> size_t *lengths, |
| cl_int *errcode_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>creates a program object for a context, and loads the source code specified |
| by the text strings in the <em>strings</em> array into the program object. |
| The devices associated with the program object are the devices associated |
| with <em>context</em>. |
| The source code specified by <em>strings</em> is either an OpenCL C program source, |
| header or implementation-defined source for custom devices that support an |
| online compiler. |
| OpenCL C++ is not supported as an online-compiled kernel language through |
| this interface.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>context</em> must be a valid OpenCL context.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>strings</em> is an array of <em>count</em> pointers to optionally null-terminated |
| character strings that make up the source code.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <em>lengths</em> argument is an array with the number of chars in each string |
| (the string length). |
| If an element in <em>lengths</em> is zero, its accompanying string is |
| null-terminated. |
| If <em>lengths</em> is <code>NULL</code>, all strings in the <em>strings</em> argument are considered |
| null-terminated. |
| Any length value passed in that is greater than zero excludes the null |
| terminator in its count.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>errcode_ret</em> will return an appropriate error code. |
| If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreateProgramWithSource</strong> returns a valid non-zero program object and |
| <em>errcode_ret</em> is set to CL_SUCCESS if the program object is created |
| successfully. |
| Otherwise, it returns a <code>NULL</code> value with one of the following error values |
| returned in <em>errcode_ret</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>count</em> is zero or if <em>strings</em> or any entry in |
| <em>strings</em> is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_program clCreateProgramWithIL(cl_context context, |
| <span class="directive">const</span> <span class="directive">void</span> *il, |
| size_t length, |
| cl_int *errcode_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>creates a program object for a context, and loads the IL pointed to by <em>il</em> |
| and with length in bytes <em>length</em> into the program object. The devices |
| associated with the program object are the devices associated with <em>context</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>context</em> must be a valid OpenCL context.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>il</em> is a pointer to a <em>length</em>-byte block of memory containing SPIR-V or an |
| implementation-defined intermediate language.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>errcode_ret</em> will return an appropriate error code. |
| If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreateProgramWithIL</strong> returns a valid non-zero program object and |
| <em>errcode_ret</em> is set to CL_SUCCESS if the program object is created |
| successfully. |
| Otherwise, it returns a <code>NULL</code> value with one of the following error values |
| returned in <em>errcode_ret</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>il</em> is <code>NULL</code> or if <em>length</em> is zero.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if the <em>length</em>-byte memory pointed to by <em>il</em> does not |
| contain well-formed intermediate language input that can be consumed by |
| the OpenCL runtime.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_program clCreateProgramWithBinary(cl_context context, |
| cl_uint num_devices, |
| <span class="directive">const</span> cl_device_id *device_list, |
| <span class="directive">const</span> size_t *lengths, |
| <span class="directive">const</span> <span class="predefined-type">unsigned</span> <span class="predefined-type">char</span> **binaries, |
| cl_int *binary_status, |
| cl_int *errcode_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>creates a program object for a context, and loads the binary bits specified |
| by <em>binary</em> into the program object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>context</em> must be a valid OpenCL context.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>device_list</em> is a pointer to a list of devices that are in <em>context</em>. |
| <em>device_list</em> must be a non-<code>NULL</code> value. |
| The binaries are loaded for devices specified in this list.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>num_devices</em> is the number of devices listed in <em>device_list</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The devices associated with the program object will be the list of devices |
| specified by <em>device_list</em>. |
| The list of devices specified by <em>device_list</em> must be devices associated |
| with <em>context</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>lengths</em> is an array of the size in bytes of the program binaries to be |
| loaded for devices specified by <em>device_list</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>binaries</em> is an array of pointers to program binaries to be loaded for |
| devices specified by <em>device_list</em>. |
| For each device given by <em>device_list</em>[i], the pointer to the program binary |
| for that device is given by <em>binaries</em>[i] and the length of this |
| corresponding binary is given by <em>lengths</em>[i]. |
| <em>lengths</em>[i] cannot be zero and <em>binaries</em>[i] cannot be a <code>NULL</code> pointer.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The program binaries specified by <em>binaries</em> contain the bits that describe |
| one of the following:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>a program executable to be run on the device(s) associated with |
| <em>context</em>,</p> |
| </li> |
| <li> |
| <p>a compiled program for device(s) associated with <em>context</em>, or</p> |
| </li> |
| <li> |
| <p>a library of compiled programs for device(s) associated with <em>context</em>.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The program binary can consist of either or both:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Device-specific code and/or,</p> |
| </li> |
| <li> |
| <p>Implementation-specific intermediate representation (IR) which will be |
| converted to the device-specific code.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p><em>binary_status</em> returns whether the program binary for each device specified |
| in <em>device_list</em> was loaded successfully or not. |
| It is an array of <em>num_devices</em> entries and returns CL_SUCCESS in |
| <em>binary_status</em>[i] if binary was successfully loaded for device specified by |
| <em>device_list</em>[i]; otherwise returns CL_INVALID_VALUE if <em>lengths</em>[i] is zero |
| or if <em>binaries</em>[i] is a <code>NULL</code> value or CL_INVALID_BINARY in |
| <em>binary_status</em>[i] if program binary is not a valid binary for the specified |
| device. |
| If <em>binary_status</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>errcode_ret</em> will return an appropriate error code. |
| If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreateProgramWithBinary</strong> returns a valid non-zero program object and |
| <em>errcode_ret</em> is set to CL_SUCCESS if the program object is created |
| successfully. |
| Otherwise, it returns a <code>NULL</code> value with one of the following error values |
| returned in <em>errcode_ret</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>device_list</em> is <code>NULL</code> or <em>num_devices</em> is zero.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_DEVICE if OpenCL devices listed in <em>device_list</em> are not in |
| the list of devices associated with <em>context</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>lengths</em> or <em>binaries</em> are <code>NULL</code> or if any entry |
| in <em>lengths</em>[i] is zero or <em>binaries</em>[i] is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_BINARY if an invalid program binary was encountered for any |
| device. |
| <em>binary_status</em> will return specific status for each device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>OpenCL allows applications to create a program object using the program |
| source or binary and build appropriate program executables. |
| This can be very useful as it allows applications to load program source and |
| then compile and link to generate a program executable online on its first |
| instance for appropriate OpenCL devices in the system. |
| These executables can now be queried and cached by the application. |
| The cached executables can be read and loaded by the application, which can |
| help significantly reduce the application initialization time.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_program clCreateProgramWithBuiltInKernels(cl_context context, |
| cl_uint num_devices, |
| <span class="directive">const</span> cl_device_id *device_list, |
| <span class="directive">const</span> <span class="predefined-type">char</span> *kernel_names, |
| cl_int *errcode_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>creates a program object for a context, and loads the information related to |
| the built-in kernels into a program object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>context</em> must be a valid OpenCL context.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>num_devices</em> is the number of devices listed in <em>device_list</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>device_list</em> is a pointer to a list of devices that are in <em>context</em>. |
| <em>device_list</em> must be a non-<code>NULL</code> value. |
| The built-in kernels are loaded for devices specified in this list.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The devices associated with the program object will be the list of devices |
| specified by <em>device_list</em>. |
| The list of devices specified by <em>device_list</em> must be devices associated |
| with <em>context</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>kernel_names</em> is a semi-colon separated list of built-in kernel names.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreateProgramWithBuiltInKernels</strong> returns a valid non-zero program object |
| and <em>errcode_ret</em> is set to CL_SUCCESS if the program object is created |
| successfully. |
| Otherwise, it returns a <code>NULL</code> value with one of the following error values |
| returned in <em>errcode_ret</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>device_list</em> is <code>NULL</code> or <em>num_devices</em> is zero.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>kernel_names</em> is <code>NULL</code> or <em>kernel_names</em> contains |
| a kernel name that is not supported by any of the devices in |
| <em>device_list</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_DEVICE if devices listed in <em>device_list</em> are not in the list |
| of devices associated with <em>context</em>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_retaining_and_releasing_program_objects">5.8.2. Retaining and Releasing Program Objects</h4> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clRetainProgram(cl_program program)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>increments the <em>program</em> reference count. |
| All <strong>clCreateProgram</strong> APIs do an implicit retain. |
| <strong>clRetainProgram</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_PROGRAM if <em>program</em> is not a valid program object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clReleaseProgram(cl_program program)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>decrements the <em>program</em> reference count. |
| The program object is deleted after all kernel objects associated with |
| <em>program</em> have been deleted and the <em>program</em> reference count becomes zero. |
| <strong>clReleaseProgram</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_PROGRAM if <em>program</em> is not a valid program object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Using this function to release a reference that was not obtained by creating |
| the object or by calling <strong>clRetainProgram</strong> causes undefined behavior.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clSetProgramReleaseCallback(cl_program program, |
| <span class="directive">void</span> (CL_CALLBACK *pfn_notify) |
| (cl_program prog, |
| <span class="directive">void</span> *user_data), |
| <span class="directive">void</span> *user_data)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>registers a user callback function with a program object. |
| Each call to <strong>clSetProgramReleaseCallback</strong> registers the specified user |
| callback function on a callback stack associated with program. |
| The registered user callback functions are called in the reverse order in |
| which they were registered. |
| The user callback functions are called after destructors (if any) for |
| program scope global variables (if any) are called and before the program is |
| released. |
| This provides a mechanism for the application (and libraries) to be notified |
| when destructors are complete.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>program</em> is a valid program object</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>pfn_notify</em> is the callback function that can be registered by the |
| application. |
| This callback function may be called asynchronously by the OpenCL |
| implementation. |
| It is the applications responsibility to ensure that the callback function |
| is thread safe. |
| The parameters to this callback function are:</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>prog</em> is the program object whose destructors are being called. |
| When the user callback is called by the implementation, this program object |
| is not longer valid. |
| prog is only provided for reference purposes.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>user_data</em> is a pointer to user supplied data. |
| <em>user_data</em> will be passed as the <em>user_data</em> argument when <em>pfn_notify</em> is |
| called. |
| user data can be <code>NULL</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clSetProgramReleaseCallback</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_PROGRAM if <em>program</em> is not a valid program object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>pfn_notify</em> is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_setting_spir_v_specialization_constants">5.8.3. Setting SPIR-V specialization constants</h4> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clSetProgramSpecializationConstant(cl_program program, |
| cl_uint spec_id, |
| size_t spec_size, |
| <span class="directive">const</span> <span class="directive">void</span> *spec_value)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>sets the value of a specialization constant.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>program</em> must be a valid OpenCL program created from an intermediate format |
| module (e.g. SPIR-V).</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>spec</em> id_ identifies the specialization constant whose value will be |
| set.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>spec_size</em> specifies the size in bytes of the data pointed to by |
| <em>spec_value</em>. |
| This should be 1 for boolean constants. |
| For all other constant types this should match the size of the |
| specialization constant in the module.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>spec_value</em> is a pointer to the memory location that contains the value of |
| the specialization constant. |
| The data pointed to by <em>spec_value</em> are copied and can be safely reused by |
| the application after <strong>clSetProgramSpecializationConstant</strong> returns. |
| This specialization value will be used by subsequent calls to |
| <strong>clBuildProgram</strong> until another call to <strong>clSetProgramSpecializationConstant</strong> |
| changes it. |
| If a specialization constant is a boolean constant, <em>spec_value</em> should be a |
| pointer to a cl_uchar value. |
| A value of zero will set the specialization constant to false; any other |
| value will set it to true.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Calling this function multiple times for the same specialization constant |
| shall cause the last provided value to override any previously specified |
| value. |
| The values are used by a subsequent <strong>clBuildProgram</strong> call for the <em>program</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Application is not required to provide values for every specialization |
| constant contained in the module. If the value is not set by this API |
| call, default values will be used during the build.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clSetProgramSpecializationConstant</strong> returns CL_SUCCESS if the function is |
| executed successfully.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_PROGRAM if <em>program</em> is not a valid program object created |
| from a module in an intermediate format (e.g. SPIR-V).</p> |
| </li> |
| <li> |
| <p>CL_INVALID_SPEC_ID if <em>spec_id</em> is not a valid specialization constant |
| ID</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>spec_size</em> does not match the size of the |
| specialization constant in the module, or if <em>spec_value</em> is |
| <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_building_program_executables">5.8.4. Building Program Executables</h4> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clBuildProgram(cl_program program, |
| cl_uint num_devices, |
| <span class="directive">const</span> cl_device_id *device_list, |
| <span class="directive">const</span> <span class="predefined-type">char</span> *options, |
| <span class="directive">void</span> (CL_CALLBACK *pfn_notify) |
| (cl_program program, |
| <span class="directive">void</span> *user_data), |
| <span class="directive">void</span> *user_data)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>builds (compiles & links) a program executable from the program source or |
| binary for all the devices or a specific device(s) in the OpenCL context |
| associated with <em>program</em>. |
| OpenCL allows program executables to be built using the source or the |
| binary. |
| <strong>clBuildProgram</strong> must be called for <em>program</em> created using |
| <strong>clCreateProgramWithSource</strong>, <strong>clCreateProgramWithIL</strong> or |
| <strong>clCreateProgramWithBinary</strong> to build the program executable for one or more |
| devices associated with <em>program</em>. |
| If <em>program</em> is created with <strong>clCreateProgramWithBinary</strong>, then the program |
| binary must be an executable binary (not a compiled binary or library).</p> |
| </div> |
| <div class="paragraph"> |
| <p>The executable binary can be queried using <strong>clGetProgramInfo</strong>(<em>program</em>, |
| CL_PROGRAM_BINARIES, …​) and can be specified to |
| <strong>clCreateProgramWithBinary</strong> to create a new program object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>program</em> is the program object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>device_list</em> is a pointer to a list of devices associated with <em>program</em>. |
| If <em>device_list</em> is a <code>NULL</code> value, the program executable is built for all |
| devices associated with <em>program</em> for which a source or binary has been |
| loaded. |
| If <em>device_list</em> is a non-<code>NULL</code> value, the program executable is built for |
| devices specified in this list for which a source or binary has been loaded.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>num_devices</em> is the number of devices listed in <em>device_list</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>options</em> is a pointer to a null-terminated string of characters that |
| describes the build options to be used for building the program executable. |
| The list of supported options is described in <a href="#compiler-options">Compiler |
| Options</a>. |
| If the program was created using <strong>clCreateProgramWithBinary</strong> and <em>options</em> |
| is a <code>NULL</code> pointer, the program will be built as if <em>options</em> were the same |
| as when the program binary was originally built. |
| If the program was created using <strong>clCreateProgramWithBinary</strong> and <em>options</em> |
| string contains anything other than the same options in the same order |
| (whitespace ignored) as when the program binary was originally built, then |
| the behavior is implementation defined.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>pfn_notify</em> is a function pointer to a notification routine. |
| The notification routine is a callback function that an application can |
| register and which will be called when the program executable has been built |
| (successfully or unsuccessfully). |
| If <em>pfn_notify</em> is not <code>NULL</code>, <strong>clBuildProgram</strong> does not need to wait for |
| the build to complete and can return immediately once the build operation |
| can begin. |
| The build operation can begin if the context, program whose sources are |
| being compiled and linked, list of devices and build options specified are |
| all valid and appropriate host and device resources needed to perform the |
| build are available. |
| If <em>pfn_notify</em> is <code>NULL</code>, <strong>clBuildProgram</strong> does not return until the build |
| has completed. |
| This callback function may be called asynchronously by the OpenCL |
| implementation. |
| It is the applications responsibility to ensure that the callback function |
| is thread-safe.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>user_data</em> will be passed as an argument when <em>pfn_notify</em> is called. |
| <em>user_data</em> can be <code>NULL</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clBuildProgram</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_PROGRAM if <em>program</em> is not a valid program object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>device_list</em> is <code>NULL</code> and <em>num_devices</em> is greater |
| than zero, or if <em>device_list</em> is not <code>NULL</code> and <em>num_devices</em> is zero.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>pfn_notify</em> is <code>NULL</code> but <em>user_data</em> is not |
| <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_DEVICE if OpenCL devices listed in <em>device_list</em> are not in |
| the list of devices associated with <em>program</em></p> |
| </li> |
| <li> |
| <p>CL_INVALID_BINARY if <em>program</em> is created with |
| <strong>clCreateProgramWithBinary</strong> and devices listed in <em>device_list</em> do not |
| have a valid program binary loaded.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_BUILD_OPTIONS if the build options specified by <em>options</em> are |
| invalid.</p> |
| </li> |
| <li> |
| <p>CL_COMPILER_NOT_AVAILABLE if <em>program</em> is created with |
| <strong>clCreateProgramWithSource</strong> and a compiler is not available i.e. |
| CL_DEVICE_COMPILER_AVAILABLE specified in the |
| <a href="#device-queries-table">Device Queries</a> table is set to CL_FALSE.</p> |
| </li> |
| <li> |
| <p>CL_BUILD_PROGRAM_FAILURE if there is a failure to build the program |
| executable. |
| This error will be returned if <strong>clBuildProgram</strong> does not return until |
| the build has completed.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if the build of a program executable for any of the |
| devices listed in <em>device_list</em> by a previous call to <strong>clBuildProgram</strong> |
| for <em>program</em> has not completed.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if there are kernel objects attached to <em>program</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if <em>program</em> was not created with |
| <strong>clCreateProgramWithSource</strong>, <strong>clCreateProgramWithIL</strong> or |
| <strong>clCreateProgramWithBinary</strong>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_separate_compilation_and_linking_of_programs">5.8.5. Separate Compilation and Linking of Programs</h4> |
| <div class="paragraph"> |
| <p>OpenCL programs are compiled and linked to support the following:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Separate compilation and link stages. |
| Program sources can be compiled to generate a compiled binary object and |
| linked in a separate stage with other compiled program objects to the |
| program executable.</p> |
| </li> |
| <li> |
| <p>Embedded headers. |
| In OpenCL 1.0 and 1.1, the I build option could be used to specify the |
| list of directories to be searched for headers files that are included |
| by a program source(s). |
| OpenCL 1.2 extends this by allowing the header sources to come from |
| program objects instead of just header files.</p> |
| </li> |
| <li> |
| <p>Libraries. |
| The linker can be used to link compiled objects and libraries into a |
| program executable or to create a library of compiled binaries.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clCompileProgram(cl_program program, |
| cl_uint num_devices, |
| <span class="directive">const</span> cl_device_id *device_list, |
| <span class="directive">const</span> <span class="predefined-type">char</span> *options, |
| cl_uint num_input_headers, |
| <span class="directive">const</span> cl_program *input_headers, |
| <span class="directive">const</span> <span class="predefined-type">char</span> **header_include_names, |
| <span class="directive">void</span> (CL_CALLBACK *pfn_notify) |
| (cl_program program, |
| <span class="directive">void</span> *user_data), |
| <span class="directive">void</span> *user_data)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>compiles a programs source for all the devices or a specific device(s) in |
| the OpenCL context associated with <em>program</em>. |
| The pre-processor runs before the program sources are compiled. |
| The compiled binary is built for all devices associated with <em>program</em> or |
| the list of devices specified. |
| The compiled binary can be queried using <strong>clGetProgramInfo</strong>(<em>program</em>, |
| CL_PROGRAM_BINARIES, …​) and can be passed to <strong>clCreateProgramWithBinary</strong> |
| to create a new program object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>program</em> is the program object that is the compilation target.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>device_list</em> is a pointer to a list of devices associated with <em>program</em>. |
| If <em>device_list</em> is a <code>NULL</code> value, the compile is performed for all devices |
| associated with <em>program</em>. |
| If <em>device_list</em> is a non-<code>NULL</code> value, the compile is performed for devices |
| specified in this list.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>num_devices</em> is the number of devices listed in <em>device_list</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>options</em> is a pointer to a null-terminated string of characters that |
| describes the compilation options to be used for building the program |
| executable. |
| Certain options are ignored when program is created with IL. |
| The list of supported options is as described in <a href="#compiler-options">Compiler Options</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>num_input_headers</em> specifies the number of programs that describe headers |
| in the array referenced by <em>input_headers</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>input_headers</em> is an array of program embedded headers created with |
| <strong>clCreateProgramWithSource</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>header_include_names</em> is an array that has a one to one correspondence with |
| <em>input_headers</em>. |
| Each entry in <em>header_include_names</em> specifies the include name used by |
| source in <em>program</em> that comes from an embedded header. |
| The corresponding entry in <em>input_headers</em> identifies the program object |
| which contains the header source to be used. |
| The embedded headers are first searched before the headers in the list of |
| directories specified by the <code>-I</code> compile option (as described in |
| <a href="#preprocessor-options">Preprocessor options</a>). |
| If multiple entries in <em>header_include_names</em> refer to the same header name, |
| the first one encountered will be used.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>program</em> was created using <strong>clCreateProgramWithIL</strong>, then |
| <em>num_input_headers</em>, <em>input_headers</em>, and <em>header_include_names</em> are |
| ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example, consider the following program source:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c"><span class="preprocessor">#include</span> <span class="include"><foo.h></span> |
| <span class="preprocessor">#include</span> <span class="include"><mydir/myinc.h></span> |
| __kernel <span class="directive">void</span> |
| image_filter (<span class="predefined-type">int</span> n, <span class="predefined-type">int</span> m, |
| __constant <span class="predefined-type">float</span> *filter_weights, |
| __read_only image2d_t src_image, |
| __write_only image2d_t dst_image) |
| { |
| ... |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This kernel includes two headers foo.h and mydir/myinc.h. |
| The following describes how these headers can be passed as embedded headers |
| in program objects:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_program foo_pg = clCreateProgramWithSource(context, |
| <span class="integer">1</span>, &foo_header_src, <span class="predefined-constant">NULL</span>, &err); |
| cl_program myinc_pg = clCreateProgramWithSource(context, |
| <span class="integer">1</span>, &myinc_header_src, <span class="predefined-constant">NULL</span>, &err); |
| |
| <span class="comment">// lets assume the program source described above is given</span> |
| <span class="comment">// by program_A and is loaded via clCreateProgramWithSource</span> |
| cl_program input_headers[<span class="integer">2</span>] = { foo_pg, myinc_pg }; |
| <span class="predefined-type">char</span> * input_header_names[<span class="integer">2</span>] = { foo.h, mydir/myinc.h }; |
| clCompileProgram(program_A, |
| <span class="integer">0</span>, <span class="predefined-constant">NULL</span>, <span class="comment">// num_devices & device_list</span> |
| <span class="predefined-constant">NULL</span>, <span class="comment">// compile_options</span> |
| <span class="integer">2</span>, <span class="comment">// num_input_headers</span> |
| input_headers, |
| input_header_names, |
| <span class="predefined-constant">NULL</span>, <span class="predefined-constant">NULL</span>); <span class="comment">// pfn_notify & user_data</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><em>pfn_notify</em> is a function pointer to a notification routine. |
| The notification routine is a callback function that an application can |
| register and which will be called when the program executable has been built |
| (successfully or unsuccessfully). |
| If <em>pfn_notify</em> is not <code>NULL</code>, <strong>clCompileProgram</strong> does not need to wait for |
| the compiler to complete and can return immediately once the compilation can |
| begin. |
| The compilation can begin if the context, program whose sources are being |
| compiled, list of devices, input headers, programs that describe input |
| headers and compiler options specified are all valid and appropriate host |
| and device resources needed to perform the compile are available. |
| If <em>pfn_notify</em> is <code>NULL</code>, <strong>clCompileProgram</strong> does not return until the |
| compiler has completed. |
| This callback function may be called asynchronously by the OpenCL |
| implementation. |
| It is the applications responsibility to ensure that the callback function |
| is thread-safe.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>user_data</em> will be passed as an argument when <em>pfn_notify</em> is called. |
| <em>user_data</em> can be <code>NULL</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCompileProgram</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_PROGRAM if <em>program</em> is not a valid program object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>device_list</em> is <code>NULL</code> and <em>num_devices</em> is greater |
| than zero, or if <em>device_list</em> is not <code>NULL</code> and <em>num_devices</em> is zero.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>num_input_headers</em> is zero and |
| <em>header_include_names</em> or <em>input_headers</em> are not <code>NULL</code> or if |
| <em>num_input_headers</em> is not zero and <em>header_include_names</em> or |
| <em>input_headers</em> are <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>pfn_notify</em> is <code>NULL</code> but <em>user_data</em> is not |
| <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_DEVICE if OpenCL devices listed in <em>device_list</em> are not in |
| the list of devices associated with <em>program</em></p> |
| </li> |
| <li> |
| <p>CL_INVALID_COMPILER_OPTIONS if the compiler options specified by |
| <em>options</em> are invalid.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if the compilation or build of a program executable |
| for any of the devices listed in <em>device_list</em> by a previous call to |
| <strong>clCompileProgram</strong> or <strong>clBuildProgram</strong> for <em>program</em> has not completed.</p> |
| </li> |
| <li> |
| <p>CL_COMPILER_NOT_AVAILABLE if a compiler is not available i.e. |
| CL_DEVICE_COMPILER_AVAILABLE specified in the |
| <a href="#device-queries-table">Device Queries</a> table is set to CL_FALSE.</p> |
| </li> |
| <li> |
| <p>CL_COMPILE_PROGRAM_FAILURE if there is a failure to compile the program |
| source. |
| This error will be returned if <strong>clCompileProgram</strong> does not return until |
| the compile has completed.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if there are kernel objects attached to <em>program</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if <em>program</em> has no source or IL available, i.e. it |
| has not been created with <strong>clCreateProgramWithSource</strong> or |
| <strong>clCreateProgramWithIL</strong>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_program clLinkProgram(cl_context context, |
| cl_uint num_devices, |
| <span class="directive">const</span> cl_device_id *device_list, |
| <span class="directive">const</span> <span class="predefined-type">char</span> *options, |
| cl_uint num_input_programs, |
| <span class="directive">const</span> cl_program *input_programs, |
| <span class="directive">void</span> (CL_CALLBACK *pfn_notify) |
| (cl_program program, |
| <span class="directive">void</span> *user_data), |
| <span class="directive">void</span> *user_data, |
| cl_int *errcode_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>links a set of compiled program objects and libraries for all the devices or |
| a specific device(s) in the OpenCL context and creates a library or |
| executable. |
| <strong>clLinkProgram</strong> creates a new program object which contains the library or |
| executable. |
| The library or executable binary can be queried using |
| <strong>clGetProgramInfo</strong>(<em>program</em>, CL_PROGRAM_BINARIES, …​) and can be specified |
| to <strong>clCreateProgramWithBinary</strong> to create a new program object.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The devices associated with the returned program object will be the list of |
| devices specified by <em>device_list</em> or if <em>device_list</em> is <code>NULL</code> it will be |
| the list of devices associated with <em>context</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>context</em> must be a valid OpenCL context.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>device_list</em> is a pointer to a list of devices that are in <em>context</em>. |
| If <em>device_list</em> is a <code>NULL</code> value, the link is performed for all devices |
| associated with <em>context</em> for which a compiled object is available. |
| If <em>device_list</em> is a non-<code>NULL</code> value, the link is performed for devices |
| specified in this list for which a compiled object is available.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>num_devices</em> is the number of devices listed in <em>device_list</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>options</em> is a pointer to a null-terminated string of characters that |
| describes the link options to be used for building the program executable. |
| The list of supported options is as described in <a href="#linker-options">Linker |
| Options</a>. |
| If the program was created using <strong>clCreateProgramWithBinary</strong> and <em>options</em> |
| is a <code>NULL</code> pointer, the program will be linked as if <em>options</em> were the |
| same as when the program binary was originally built. |
| If the program was created using <strong>clCreateProgramWithBinary</strong> and <em>options</em> |
| string contains anything other than the same options in the same order |
| (whitespace ignored) as when the program binary was originally built, then |
| the behavior is implementation defined.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>num_input_programs</em> specifies the number of programs in array referenced by |
| <em>input_programs</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>input_programs</em> is an array of program objects that are compiled binaries |
| or libraries that are to be linked to create the program executable. |
| For each device in <em>device_list</em> or if <em>device_list</em> is <code>NULL</code> the list of |
| devices associated with context, the following cases occur:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>All programs specified by <em>input_programs</em> contain a compiled binary or |
| library for the device. |
| In this case, a link is performed to generate a program executable for |
| this device.</p> |
| </li> |
| <li> |
| <p>None of the programs contain a compiled binary or library for that |
| device. |
| In this case, no link is performed and there will be no program |
| executable generated for this device.</p> |
| </li> |
| <li> |
| <p>All other cases will return a CL_INVALID_OPERATION error.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p><em>pfn_notify</em> is a function pointer to a notification routine. |
| The notification routine is a callback function that an application can |
| register and which will be called when the program executable has been built |
| (successfully or unsuccessfully).</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>pfn_notify</em> is not <code>NULL</code>, <strong>clLinkProgram</strong> does not need to wait for the |
| linker to complete and can return immediately once the linking operation can |
| begin. |
| Once the linker has completed, the <em>pfn_notify</em> callback function is called |
| which returns the program object returned by <strong>clLinkProgram</strong>. |
| The application can query the link status and log for this program object. |
| This callback function may be called asynchronously by the OpenCL |
| implementation. |
| It is the applications responsibility to ensure that the callback function |
| is thread-safe.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>pfn_notify</em> is <code>NULL</code>, <strong>clLinkProgram</strong> does not return until the linker |
| has completed.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>user_data</em> will be passed as an argument when <em>pfn_notify</em> is called. |
| <em>user_data</em> can be <code>NULL</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The linking operation can begin if the context, list of devices, input |
| programs and linker options specified are all valid and appropriate host and |
| device resources needed to perform the link are available. |
| If the linking operation can begin, <strong>clLinkProgram</strong> returns a valid non-zero |
| program object.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>pfn_notify</em> is <code>NULL</code>, the <em>errcode_ret</em> will be set to CL_SUCCESS if |
| the link operation was successful and CL_LINK_PROGRAM_FAILURE if there is a |
| failure to link the compiled binaries and/or libraries.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>pfn_notify</em> is not <code>NULL</code>, <strong>clLinkProgram</strong> does not have to wait until |
| the linker to complete and can return CL_SUCCESS in <em>errcode_ret</em> if the |
| linking operation can begin. |
| The <em>pfn_notify</em> callback function will return a CL_SUCCESS or |
| CL_LINK_PROGRAM_FAILURE if the linking operation was successful or not.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Otherwise <strong>clLinkProgram</strong> returns a <code>NULL</code> program object with an |
| appropriate error in <em>errcode_ret</em>. |
| The application should query the linker status of this program object to |
| check if the link was successful or not. |
| The list of errors that can be returned are:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>device_list</em> is <code>NULL</code> and <em>num_devices</em> is greater |
| than zero, or if <em>device_list</em> is not <code>NULL</code> and <em>num_devices</em> is zero.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>num_input_programs</em> is zero and <em>input_programs</em> is |
| <code>NULL</code> or if <em>num_input_programs</em> is zero and <em>input_programs</em> is not |
| <code>NULL</code> or if <em>num_input_programs</em> is not zero and <em>input_programs</em> is |
| <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_PROGRAM if programs specified in <em>input_programs</em> are not |
| valid program objects.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>pfn_notify</em> is <code>NULL</code> but <em>user_data</em> is not |
| <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_DEVICE if OpenCL devices listed in <em>device_list</em> are not in |
| the list of devices associated with <em>context</em></p> |
| </li> |
| <li> |
| <p>CL_INVALID_LINKER_OPTIONS if the linker options specified by <em>options</em> |
| are invalid.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if the compilation or build of a program executable |
| for any of the devices listed in <em>device_list</em> by a previous call to |
| <strong>clCompileProgram</strong> or <strong>clBuildProgram</strong> for <em>program</em> has not completed.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if the rules for devices containing compiled |
| binaries or libraries as described in <em>input_programs</em> argument above |
| are not followed.</p> |
| </li> |
| <li> |
| <p>CL_LINKER_NOT_AVAILABLE if a linker is not available i.e. |
| CL_DEVICE_LINKER_AVAILABLE specified in the |
| <a href="#device-queries-table">Device Queries</a> table is set to CL_FALSE.</p> |
| </li> |
| <li> |
| <p>CL_LINK_PROGRAM_FAILURE if there is a failure to link the compiled |
| binaries and/or libraries.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="compiler-options">5.8.6. Compiler Options</h4> |
| <div class="paragraph"> |
| <p>The compiler options are categorized as pre-processor options, options for |
| math intrinsics, options that control optimization and miscellaneous |
| options. |
| This specification defines a standard set of options that must be supported |
| by the compiler when building program executables online or offline from |
| OpenCL C/C++ or, where relevant, from an IL. |
| These may be extended by a set of vendor- or platform-specific options.</p> |
| </div> |
| <div class="sect4"> |
| <h5 id="preprocessor-options">Preprocessor options</h5> |
| <div class="paragraph"> |
| <p>These options control the OpenCL C/C++ preprocessor which is run on each |
| program source before actual compilation. |
| These options are ignored for programs created with IL.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><code>-D name</code> </dt> |
| <dd> |
| <p>Predefine <em>name</em> as a macro, with definition 1.</p> |
| </dd> |
| <dt class="hdlist1"><code>-D name=definition</code> </dt> |
| <dd> |
| <p>The contents of <em>definition</em> are tokenized and processed as if they |
| appeared during translation phase three in a `#define' directive. |
| In particular, the definition will be truncated by embedded newline |
| characters.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>-D options are processed in the order they are given in the <em>options</em> |
| argument to <strong>clBuildProgram</strong> or <strong>clCompileProgram</strong>. |
| Note that a space is required between the -D option and the symbol it |
| defines, otherwise behavior is implementation defined.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><code>-I dir</code> </dt> |
| <dd> |
| <p>Add the directory <em>dir</em> to the list of directories to be searched for |
| header files. |
| <em>dir</em> can optionally be enclosed in double quotes.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>This option is not portable due to its dependency on host file system and |
| host operating system. |
| It is supported for backwards compatibility with previous OpenCL versions. |
| Developers are encouraged to create and use explicit header objects by means |
| of <strong>clCompileProgram</strong> followed by <strong>clLinkProgram</strong>.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="math-intrinsics-options">Math Intrinsics Options</h5> |
| <div class="paragraph"> |
| <p>These options control compiler behavior regarding floating-point arithmetic. |
| These options trade off between speed and correctness.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><code>-cl-single-precision-constant</code> </dt> |
| <dd> |
| <p>Treat double precision floating-point constant as single precision |
| constant. |
| This option is ignored for programs created with IL.</p> |
| </dd> |
| <dt class="hdlist1"><code>-cl-denorms-are-zero</code> </dt> |
| <dd> |
| <p>This option controls how single precision and double precision |
| denormalized numbers are handled. |
| If specified as a build option, the single precision denormalized |
| numbers may be flushed to zero; double precision denormalized numbers |
| may also be flushed to zero if the optional extension for double |
| precision is supported. |
| This is intended to be a performance hint and the OpenCL compiler can |
| choose not to flush denorms to zero if the device supports single |
| precision (or double precision) denormalized numbers.</p> |
| <div class="openblock"> |
| <div class="content"> |
| <div class="paragraph"> |
| <p>This option is ignored for single precision numbers if the device does not |
| support single precision denormalized numbers i.e. CL_FP_DENORM bit is not |
| set in CL_DEVICE_SINGLE_FP_CONFIG.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This option is ignored for double precision numbers if the device does not |
| support double precision or if it does support double precision but not |
| double precision denormalized numbers i.e. CL_FP_DENORM bit is not set in |
| CL_DEVICE_DOUBLE_FP_CONFIG.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This flag only applies for scalar and vector single precision floating-point |
| variables and computations on these floating-point variables inside a |
| program. |
| It does not apply to reading from or writing to image objects.</p> |
| </div> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1"><code>-cl-fp32-correctly-rounded-divide-sqrt</code> </dt> |
| <dd> |
| <p>The <code>-cl-fp32-correctly-rounded-divide-sqrt</code> build option to |
| <strong>clBuildProgram</strong> or <strong>clCompileProgram</strong> allows an application to specify |
| that single precision floating-point divide (x/y and 1/x) and sqrt used |
| in the program source are correctly rounded. |
| If this build option is not specified, the minimum numerical accuracy of |
| single precision floating-point divide and sqrt are as defined in the |
| SPIR-V OpenCL environment specification.</p> |
| <div class="openblock"> |
| <div class="content"> |
| <div class="paragraph"> |
| <p>This build option can only be specified if the |
| CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT is set in CL_DEVICE_SINGLE_FP_CONFIG (as |
| defined in the <a href="#device-queries-table">Device Queries</a> table) for devices |
| that the program is being build. |
| <strong>clBuildProgram</strong> or <strong>clCompileProgram</strong> will fail to compile the program for |
| a device if the <code>-cl-fp32-correctly-rounded-divide-sqrt</code> option is specified |
| and CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT is not set for the device.</p> |
| </div> |
| </div> |
| </div> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="optimization-options">Optimization Options</h5> |
| <div class="paragraph"> |
| <p>These options control various sorts of optimizations. |
| Turning on optimization flags makes the compiler attempt to improve the |
| performance and/or code size at the expense of compilation time and possibly |
| the ability to debug the program.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><code>-cl-opt-disable</code> </dt> |
| <dd> |
| <p>This option disables all optimizations. |
| The default is optimizations are enabled.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>The following options control compiler behavior regarding floating-point |
| arithmetic. |
| These options trade off between performance and correctness and must be |
| specifically enabled. |
| These options are not turned on by default since it can result in incorrect |
| output for programs which depend on an exact implementation of IEEE 754 |
| rules/specifications for math functions.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><code>-cl-mad-enable</code> </dt> |
| <dd> |
| <p>Allow <code>a * b + c</code> to be replaced by a <strong>mad</strong> instruction. |
| The <strong>mad</strong> instruction may compute <code>a * b + c</code> with reduced accuracy |
| in the embedded profile. See the SPIR-V OpenCL environment specification for |
| accuracy details. On some hardware the <strong>mad</strong> instruction may provide better |
| performance than the expanded computation.</p> |
| </dd> |
| <dt class="hdlist1"><code>-cl-no-signed-zeros</code> </dt> |
| <dd> |
| <p>Allow optimizations for floating-point arithmetic that ignore the |
| signedness of zero. |
| IEEE 754 arithmetic specifies the distinct behavior of <code>+0.0</code> and <code>-0.0</code> |
| values, which then prohibits simplification of expressions such as <code>x |
| + 0.0</code> or <code>0.0 * x</code> (even with <code>-cl-finite-math-only</code>). |
| This option implies that the sign of a zero result isn’t significant.</p> |
| </dd> |
| <dt class="hdlist1"><code>-cl-unsafe-math-optimizations</code> </dt> |
| <dd> |
| <p>Allow optimizations for floating-point arithmetic that (a) assume that |
| arguments and results are valid, (b) may violate the IEEE 754 standard, |
| (c) assume relaxed OpenCL numerical compliance requirements as defined |
| in the unsafe math optimization section of the SPIR-V OpenCL environment |
| specification, and (d) may violate edge case behavior in the SPIR-V OpenCL |
| environment specification. This option includes the <code>-cl-no-signed-zeros</code> |
| and <code>-cl-mad-enable</code> options.</p> |
| </dd> |
| <dt class="hdlist1"><code>-cl-finite-math-only</code> </dt> |
| <dd> |
| <p>Allow optimizations for floating-point arithmetic that assume that |
| arguments and results are not NaNs, +Inf, -Inf. |
| This option may violate the OpenCL numerical compliance requirements for |
| single precision and double precision floating-point, as well as edge |
| case behavior. |
| The original and modified values are defined in the SPIR-V OpenCL |
| environment specification</p> |
| </dd> |
| <dt class="hdlist1"><code>-cl-fast-relaxed-math</code> </dt> |
| <dd> |
| <p>Sets the optimization options <code>-cl-finite-math-only</code> and |
| <code>-cl-unsafe-math-optimizations</code>. |
| This option causes the preprocessor macro <code>__FAST_RELAXED_MATH__</code> to |
| be defined in the OpenCL program.</p> |
| </dd> |
| <dt class="hdlist1"><code>-cl-uniform-work-group-size</code> </dt> |
| <dd> |
| <p>This requires that the global work-size be a multiple of the work-group |
| size specified to <strong>clEnqueueNDRangeKernel</strong>. |
| Allow optimizations that are made possible by this restriction.</p> |
| </dd> |
| <dt class="hdlist1"><code>-cl-no-subgroup-ifp</code> </dt> |
| <dd> |
| <p>This indicates that kernels in this program do not require subgroups to |
| make independent forward progress. |
| Allows optimizations that are made possible by this restriction. |
| This option has no effect for devices that do not support independent |
| forward progress for subgroups.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="_options_to_request_or_suppress_warnings">Options to Request or Suppress Warnings</h5> |
| <div class="paragraph"> |
| <p>Warnings are diagnostic messages that report constructions which are not |
| inherently erroneous but which are risky or suggest there may have been an |
| error. |
| The following language-independent options do not enable specific warnings |
| but control the kinds of diagnostics produced by the OpenCL compiler. |
| These options are ignored for programs created with IL.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><code>-w</code> </dt> |
| <dd> |
| <p>Inhibit all warning messages.</p> |
| </dd> |
| <dt class="hdlist1"><code>-Werror</code> </dt> |
| <dd> |
| <p>Make all warnings into errors.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="opencl-c-version">Options Controlling the OpenCL C version</h5> |
| <div class="paragraph"> |
| <p>The following option controls the version of OpenCL C that the compiler |
| accepts. |
| These options are ignored for programs created with IL.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><code>-cl-std=</code> </dt> |
| <dd> |
| <p>Determine the OpenCL C language version to use. |
| A value for this option must be provided. |
| Valid values are:</p> |
| <div class="openblock"> |
| <div class="content"> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL1.1 Support all OpenCL C programs that use the OpenCL C language |
| features defined in <em>section 6</em> of the OpenCL 1.1 specification.</p> |
| </li> |
| <li> |
| <p>CL1.2 Support all OpenCL C programs that use the OpenCL C language |
| features defined in <em>section 6</em> of the OpenCL 1.2 specification.</p> |
| </li> |
| <li> |
| <p>CL2.0 Support all OpenCL C programs that use the OpenCL C language |
| features defined in <em>section 6</em> of the OpenCL C 2.0 specification.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>Calls to <strong>clBuildProgram</strong> or <strong>clCompileProgram</strong> with the <code>-cl-std=CL1.1</code> |
| option <strong>will fail</strong> to compile the program for any devices with |
| CL_DEVICE_OPENCL_C_VERSION = OpenCL C 1.0.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Calls to <strong>clBuildProgram</strong> or <strong>clCompileProgram</strong> with the <code>-cl-std=CL1.2</code> |
| option <strong>will fail</strong> to compile the program for any devices with |
| CL_DEVICE_OPENCL_C_VERSION = OpenCL C 1.0.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Calls to <strong>clBuildProgram</strong> or <strong>clCompileProgram</strong> with the <code>-cl-std=CL2.0</code> |
| option <strong>will fail</strong> to compile the program for any devices with |
| CL_DEVICE_OPENCL_C_VERSION = OpenCL C 1.0, OpenCL C 1.1 or OpenCL C 1.2.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the cl-std build option is not specified, the highest OpenCL C 1.x |
| language version supported by each device is used when compiling the program |
| for each device. |
| Applications are required to specify the cl-std=CL2.0 option if they want to |
| compile or build their programs with OpenCL C 2.0.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="_options_for_querying_kernel_argument_information">Options for Querying Kernel Argument Information</h5> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><code>-cl-kernel-arg-info</code> </dt> |
| <dd> |
| <p>This option allows the compiler to store information about the arguments |
| of a kernel(s) in the program executable. |
| The argument information stored includes the argument name, its type, |
| the address space and access qualifiers used. |
| Refer to description of <strong>clGetKernelArgInfo</strong> on how to query this |
| information.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="_options_for_debugging_your_program">Options for debugging your program</h5> |
| <div class="paragraph"> |
| <p>The following option is available.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><code>-g</code> </dt> |
| <dd> |
| <p>This option can currently be used to generate additional errors for the |
| built-in functions that allow you to enqueue commands on a device (refer |
| to OpenCL kernel languages specifications).</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="linker-options">5.8.7. Linker Options</h4> |
| <div class="paragraph"> |
| <p>This specification defines a standard set of linker options that must be |
| supported by the OpenCL C compiler when linking compiled programs online or |
| offline. |
| These linker options are categorized as library linking options and program |
| linking options. |
| These may be extended by a set of vendor- or platform-specific options.</p> |
| </div> |
| <div class="sect4"> |
| <h5 id="_library_linking_options">Library Linking Options</h5> |
| <div class="paragraph"> |
| <p>The following options can be specified when creating a library of compiled |
| binaries.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><code>-create-library</code> </dt> |
| <dd> |
| <p>Create a library of compiled binaries specified in <em>input_programs</em> |
| argument to <strong>clLinkProgram</strong>.</p> |
| </dd> |
| <dt class="hdlist1"><code>-enable-link-options</code> </dt> |
| <dd> |
| <p>Allows the linker to modify the library behavior based on one or more |
| link options (described in <a href="#program-linking-options">Program Linking |
| Options</a>) when this library is linked with a program executable. |
| This option must be specified with the create-library option.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="program-linking-options">Program Linking Options</h5> |
| <div class="paragraph"> |
| <p>The following options can be specified when linking a program executable.</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>-cl-denorms-are-zero</code><br> |
| <code>-cl-no-signed-zeroes</code><br> |
| <code>-cl-unsafe-math-optimizations</code><br> |
| <code>-cl-finite-math-only</code><br> |
| <code>-cl-fast-relaxed-math</code><br> |
| <code>-cl-no-subgroup-ifp</code></p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p>The options are described in <a href="#math-intrinsics-options">Math Intrinsics |
| Options</a> and <a href="#optimization-options">Optimization Options</a>. |
| The linker may apply these options to all compiled program objects |
| specified to <strong>clLinkProgram</strong>. |
| The linker may apply these options only to libraries which were created |
| with the enable-link-option.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_unloading_the_opencl_compiler">5.8.8. Unloading the OpenCL Compiler</h4> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clUnloadPlatformCompiler(cl_platform_id platform)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>allows the implementation to release the resources allocated by the OpenCL |
| compiler for <em>platform</em>. |
| This is a hint from the application and does not guarantee that the compiler |
| will not be used in the future or that the compiler will actually be |
| unloaded by the implementation. |
| Calls to <strong>clBuildProgram</strong>, <strong>clCompileProgram</strong> or <strong>clLinkProgram</strong> after |
| <strong>clUnloadPlatformCompiler</strong> will reload the compiler, if necessary, to build |
| the appropriate program executable.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clUnloadPlatformCompiler</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_PLATFORM if <em>platform</em> is not a valid platform.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_program_object_queries">5.8.9. Program Object Queries</h4> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetProgramInfo(cl_program program, |
| cl_program_info param_name, |
| size_t param_value_size, |
| <span class="directive">void</span> *param_value, |
| size_t *param_value_size_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>returns information about the program object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>program</em> specifies the program object being queried.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_name</em> specifies the information to query. |
| The list of supported <em>param_name</em> types and the information returned in |
| <em>param_value</em> by <strong>clGetProgramInfo</strong> is described in the |
| <a href="#program-info-table">Program Object Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value</em> is a pointer to memory where the appropriate result being |
| queried is returned. |
| If <em>param_value</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to |
| by <em>param_value</em>. |
| This size must be ≥ size of return type as described in the |
| <a href="#program-info-table">Program Object Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size_ret</em> returns the actual size in bytes of data being |
| queried by <em>param_name</em>. |
| If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <table id="program-info-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 26. <strong>clGetProgramInfo</strong> parameter queries</caption> |
| <colgroup> |
| <col style="width: 34%;"> |
| <col style="width: 33%;"> |
| <col style="width: 33%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_program_info</strong></th> |
| <th class="tableblock halign-left valign-top">Return Type</th> |
| <th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_REFERENCE_COUNT</strong><sup>14</sup></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the <em>program</em> reference count.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_CONTEXT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_context</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the context specified when the program object is created</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_NUM_DEVICES</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the number of devices associated with <em>program</em>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_DEVICES</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_id[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the list of devices associated with the program object. |
| This can be the devices associated with context on which the program |
| object has been created or can be a subset of devices that are |
| specified when a program object is created using |
| <strong>clCreateProgramWithBinary</strong>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_SOURCE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the program source code specified by |
| <strong>clCreateProgramWithSource</strong>. |
| The source string returned is a concatenation of all source strings |
| specified to <strong>clCreateProgramWithSource</strong> with a null terminator. |
| The concatenation strips any nulls in the original source strings.</p> |
| <p class="tableblock"> If <em>program</em> is created using <strong>clCreateProgramWithBinary</strong>, |
| <strong>clCreateProgramWithIL</strong> or <strong>clCreateProgramWithBuiltinKernels</strong>, a |
| null string or the appropriate program source code is returned |
| depending on whether or not the program source code is stored in the |
| binary.</p> |
| <p class="tableblock"> The actual number of characters that represents the program source |
| code including the null terminator is returned in |
| <em>param_value_size_ret</em>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_IL</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the program IL for programs created with |
| <strong>clCreateProgramWithIL</strong>.</p> |
| <p class="tableblock"> If <em>program</em> is created with <strong>clCreateProgramWithSource</strong>, |
| <strong>clCreateProgramWithBinary</strong> or <strong>clCreateProgramWithBuiltinKernels</strong> |
| the memory pointed to by param_value will be unchanged and |
| param_value_size_retwill be set to 0.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_BINARY_SIZES</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns an array that contains the size in bytes of the program |
| binary (could be an executable binary, compiled binary or library |
| binary) for each device associated with program. |
| The size of the array is the number of devices associated with |
| program. |
| If a binary is not available for a device(s), a size of zero is |
| returned.</p> |
| <p class="tableblock"> If <em>program</em> is created using <strong>clCreateProgramWithBuiltinKernels</strong>, |
| the implementation may return zero in any entries of the returned |
| array.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_BINARIES</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">unsigned char *[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the program binaries (could be an executable binary, compiled |
| binary or library binary) for all devices associated with program. |
| For each device in program, the binary returned can be the binary |
| specified for the device when program is created with |
| <strong>clCreateProgramWithBinary</strong> or it can be the executable binary |
| generated by <strong>clBuildProgram</strong> or <strong>clLinkProgram</strong>. |
| If <em>program</em> is created with <strong>clCreateProgramWithSource</strong> or |
| <strong>clCreateProgramWithIL</strong>, the binary returned is the binary generated |
| by <strong>clBuildProgram</strong>, <strong>clCompileProgram</strong> or <strong>clLinkProgram</strong>. |
| The bits returned can be an implementation-specific intermediate |
| representation (a.k.a. IR) or device specific executable bits or |
| both. |
| The decision on which information is returned in the binary is up to |
| the OpenCL implementation.</p> |
| <p class="tableblock"> param_value points to an array of <code>n</code> pointers allocated by the |
| caller, where <code>n</code> is the number of devices associated with program. |
| The buffer sizes needed to allocate the memory that these <code>n</code> |
| pointers refer to can be queried using the CL_PROGRAM_BINARY_SIZES |
| query as described in this table.</p> |
| <p class="tableblock"> Each entry in this array is used by the implementation as the |
| location in memory where to copy the program binary for a specific |
| device, if there is a binary available. |
| To find out which device the program binary in the array refers to, |
| use the CL_PROGRAM_DEVICES query to get the list of devices. |
| There is a one-to-one correspondence between the array of n pointers |
| returned by CL_PROGRAM_BINARIES and array of devices returned by |
| CL_PROGRAM_DEVICES.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_NUM_KERNELS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of kernels declared in <em>program</em> that can be |
| created with <strong>clCreateKernel</strong>. |
| This information is only available after a successful program |
| executable has been built for at least one device in the list of |
| devices associated with <em>program</em>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_KERNEL_NAMES</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns a semi-colon separated list of kernel names in <em>program</em> |
| that can be created with <strong>clCreateKernel</strong>. |
| This information is only available after a successful program |
| executable has been built for at least one device in the list of |
| devices associated with <em>program</em>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This indicates that the <em>program</em> object contains non-trivial |
| constructor(s) that will be executed by runtime before any kernel |
| from the program is executed.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This indicates that the program object contains non-trivial |
| destructor(s) that will be executed by runtime when <em>program</em> is |
| destroyed.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">14</dt> |
| <dd> |
| <p>The reference count returned should be considered immediately stale. |
| It is unsuitable for general use in applications. |
| This feature is provided for identifying memory leaks.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clGetProgramInfo</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes |
| specified by <em>param_value_size</em> is < size of return type as described in |
| the <a href="#program-info-table">Program Object Queries</a> table and |
| <em>param_value</em> is not <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_PROGRAM if <em>program</em> is a not a valid program object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_PROGRAM_EXECUTABLE if <em>param_name</em> is CL_PROGRAM_NUM_KERNELS |
| or CL_PROGRAM_KERNEL_NAMES and a successful program executable has not |
| been built for at least one device in the list of devices associated |
| with <em>program</em>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetProgramBuildInfo(cl_program program, |
| cl_device_id device, |
| cl_program_build_info param_name, |
| size_t param_value_size, |
| <span class="directive">void</span> *param_value, |
| size_t *param_value_size_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>returns build information for each device in the program object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>program</em> specifies the program object being queried.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>device</em> specifies the device for which build information is being queried. |
| <em>device</em> must be a valid device associated with <em>program</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_name</em> specifies the information to query. |
| The list of supported <em>param_name</em> types and the information returned in |
| <em>param_value</em> by <strong>clGetProgramBuildInfo</strong> is described in the |
| <a href="#program-build-info-table">Program Build Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value</em> is a pointer to memory where the appropriate result being |
| queried is returned. |
| If <em>param_value</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to |
| by <em>param_value</em>. |
| This size must be ≥ size of return type as described in the |
| <a href="#program-build-info-table">Program Build Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size_ret</em> returns the actual size in bytes of data being |
| queried by <em>param_name</em>. |
| If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <table id="program-build-info-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 27. <strong>clGetProgramBuildInfo</strong> parameter queries.</caption> |
| <colgroup> |
| <col style="width: 34%;"> |
| <col style="width: 33%;"> |
| <col style="width: 33%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_program_build_info</strong></th> |
| <th class="tableblock halign-left valign-top">Return Type</th> |
| <th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_PROGRAM_BUILD_STATUS</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_build_status</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the build, compile or link status, whichever was performed |
| last on program for device.</p> |
| <p class="tableblock"> This can be one of the following:</p> |
| <p class="tableblock"> CL_BUILD_NONE - The build status returned if no <strong>clBuildProgram</strong>, |
| <strong>clCompileProgram</strong> or <strong>clLinkProgram</strong> has been performed on the |
| specified program object for device.</p> |
| <p class="tableblock"> CL_BUILD_ERROR - The build status returned if <strong>clBuildProgram</strong>, |
| <strong>clCompileProgram</strong> or <strong>clLinkProgram</strong> whichever was performed last |
| on the specified program object for device generated an error.</p> |
| <p class="tableblock"> CL_BUILD_SUCCESS - The build status returned if <strong>clBuildProgram</strong>, |
| <strong>clCompileProgram</strong> or <strong>clLinkProgram</strong> whichever was performed last |
| on the specified program object for device was successful.</p> |
| <p class="tableblock"> CL_BUILD_IN_PROGRESS - The build status returned if |
| <strong>clBuildProgram</strong>, <strong>clCompileProgram</strong> or <strong>clLinkProgram</strong> whichever |
| was performed last on the specified program object for device has |
| not finished.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_PROGRAM_BUILD_OPTIONS</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the build, compile or link options specified by the options |
| argument in <strong>clBuildProgram</strong>, <strong>clCompileProgram</strong> or <strong>clLinkProgram</strong>, |
| whichever was performed last on program for device.</p> |
| <p class="tableblock"> If build status of program for device is CL_BUILD_NONE, an empty |
| string is returned.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_PROGRAM_BUILD_LOG</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the build, compile or link log for <strong>clBuildProgram</strong>, |
| <strong>clCompileProgram</strong> or <strong>clLinkProgram</strong>, whichever was performed last |
| on program for device.</p> |
| <p class="tableblock"> If build status of program for device is CL_BUILD_NONE, an empty |
| string is returned.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CL_PROGRAM_BINARY_TYPE</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_program_binary_type</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the program binary type for device. |
| This can be one of the following values:</p> |
| <p class="tableblock"> CL_PROGRAM_BINARY_TYPE_NONE - There is no binary associated with |
| device.</p> |
| <p class="tableblock"> CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT - A compiled binary is |
| associated with device. |
| This is the case if program was created using |
| <strong>clCreateProgramWithSource</strong> and compiled using <strong>clCompileProgram</strong> or |
| a compiled binary is loaded using <strong>clCreateProgramWithBinary</strong>.</p> |
| <p class="tableblock"> CL_PROGRAM_BINARY_TYPE_LIBRARY - A library binary is associated with |
| device. |
| This is the case if program was created by <strong>clLinkProgram</strong> which is |
| called with the <code>-create-library</code> link option or if a library binary |
| is loaded using <strong>clCreateProgramWithBinary</strong>.</p> |
| <p class="tableblock"> CL_PROGRAM_BINARY_TYPE_EXECUTABLE - An executable binary is |
| associated with device. |
| This is the case if program was created by <strong>clLinkProgram</strong> without |
| the <code>-create-library link</code> option or program was created by |
| <strong>clBuildProgram</strong> or an executable binary is loaded using |
| <strong>clCreateProgramWithBinary</strong>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The total amount of storage, in bytes, used by program variables in |
| the global address space.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p><strong>clGetProgramBuildInfo</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_DEVICE if <em>device</em> is not in the list of devices associated |
| with <em>program</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes |
| specified by <em>param_value_size</em> is < size of return type as described in |
| the <a href="#program-build-info-table">Program Build Queries</a> table and |
| <em>param_value</em> is not <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_PROGRAM if <em>program</em> is a not a valid program object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>A program binary (compiled binary, library binary or executable binary) |
| built for a parent device can be used by all its sub-devices. |
| If a program binary has not been built for a sub-device, the program binary |
| associated with the parent device will be used.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A program binary for a device specified with <strong>clCreateProgramWithBinary</strong> or |
| queried using <strong>clGetProgramInfo</strong> can be used as the binary for the |
| associated root device, and all sub-devices created from the root-level |
| device or sub-devices thereof.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_kernel_objects">5.9. Kernel Objects</h3> |
| <div class="paragraph"> |
| <p>A kernel is a function declared in a program. |
| A kernel is identified by the <code>__kernel</code> qualifier applied to any function |
| in a program. |
| A kernel object encapsulates the specific <code>__kernel</code> function declared in |
| a program and the argument values to be used when executing this |
| <code>__kernel</code> function.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="_creating_kernel_objects">5.9.1. Creating Kernel Objects</h4> |
| <div class="paragraph"> |
| <p>To create a kernel object, use the function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_kernel clCreateKernel(cl_program program, |
| <span class="directive">const</span> <span class="predefined-type">char</span> *kernel_name, |
| cl_int *errcode_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><em>program</em> is a program object with a successfully built executable.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>kernel_name</em> is a function name in the program declared with the |
| <code>__kernel</code> qualifier.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>errcode_ret</em> will return an appropriate error code. |
| If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreateKernel</strong> returns a valid non-zero kernel object and <em>errcode_ret</em> is |
| set to CL_SUCCESS if the kernel object is created successfully. |
| Otherwise, it returns a <code>NULL</code> value with one of the following error values |
| returned in <em>errcode_ret</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_PROGRAM if <em>program</em> is not a valid program object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_PROGRAM_EXECUTABLE if there is no successfully built |
| executable for <em>program</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_KERNEL_NAME if <em>kernel_name</em> is not found in <em>program</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_KERNEL_DEFINITION if the function definition for <code>__kernel</code> |
| function given by <em>kernel_name</em> such as the number of arguments, the |
| argument types are not the same for all devices for which the <em>program</em> |
| executable has been built.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>kernel_name</em> is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clCreateKernelsInProgram(cl_program program, |
| cl_uint num_kernels, |
| cl_kernel *kernels, |
| cl_uint *num_kernels_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>creates kernel objects for all kernel functions in <em>program</em>. |
| Kernel objects are not created for any <code>__kernel</code> functions in <em>program</em> |
| that do not have the same function definition across all devices for which a |
| program executable has been successfully built.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>program</em> is a program object with a successfully built executable.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>num_kernels</em> is the size of memory pointed to by <em>kernels</em> specified as the |
| number of cl_kernel entries.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>kernels</em> is the buffer where the kernel objects for kernels in <em>program</em> |
| will be returned. |
| If <em>kernels</em> is <code>NULL</code>, it is ignored. |
| If <em>kernels</em> is not <code>NULL</code>, <em>num_kernels</em> must be greater than or equal to |
| the number of kernels in <em>program</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>num_kernels_ret</em> is the number of kernels in <em>program</em>. |
| If <em>num_kernels_ret</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreateKernelsInProgram</strong> will return CL_SUCCESS if the kernel objects were |
| successfully allocated. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_PROGRAM if <em>program</em> is not a valid program object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_PROGRAM_EXECUTABLE if there is no successfully built |
| executable for any device in <em>program</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>kernels</em> is not <code>NULL</code> and <em>num_kernels</em> is less |
| than the number of kernels in <em>program</em>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Kernel objects can only be created once you have a program object with a |
| valid program source or binary loaded into the program object and the |
| program executable has been successfully built for one or more devices |
| associated with program. |
| No changes to the program executable are allowed while there are kernel |
| objects associated with a program object. |
| This means that calls to <strong>clBuildProgram</strong> and <strong>clCompileProgram</strong> return |
| CL_INVALID_OPERATION if there are kernel objects attached to a program |
| object. |
| The OpenCL context associated with <em>program</em> will be the context associated |
| with <em>kernel</em>. |
| The list of devices associated with <em>program</em> are the devices associated |
| with <em>kernel</em>. |
| Devices associated with a program object for which a valid program |
| executable has been built can be used to execute kernels declared in the |
| program object.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clRetainKernel(cl_kernel kernel)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>increments the <em>kernel</em> reference count. |
| <strong>clRetainKernel</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_KERNEL if <em>kernel</em> is not a valid kernel object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreateKernel</strong> or <strong>clCreateKernelsInProgram</strong> do an implicit retain.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clReleaseKernel(cl_kernel kernel)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>decrements the <em>kernel</em> reference count. |
| <strong>clReleaseKernel</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_KERNEL if <em>kernel</em> is not a valid kernel object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The kernel object is deleted once the number of instances that are retained |
| to <em>kernel</em> become zero and the kernel object is no longer needed by any |
| enqueued commands that use <em>kernel</em>. |
| Using this function to release a reference that was not obtained by creating |
| the object or by calling <strong>clRetainKernel</strong> causes undefined behavior.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_setting_kernel_arguments">5.9.2. Setting Kernel Arguments</h4> |
| <div class="paragraph"> |
| <p>To execute a kernel, the kernel arguments must be set.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clSetKernelArg(cl_kernel kernel, |
| cl_uint arg_index, |
| size_t arg_size, |
| <span class="directive">const</span> <span class="directive">void</span> *arg_value)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>is used to set the argument value for a specific argument of a kernel.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>kernel</em> is a valid kernel object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>arg_index</em> is the argument index. |
| Arguments to the kernel are referred by indices that go from 0 for the |
| leftmost argument to <em>n</em> - 1, where <em>n</em> is the total number of arguments |
| declared by a kernel.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example, consider the following kernel:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span> image_filter (<span class="predefined-type">int</span> n, |
| <span class="predefined-type">int</span> m, |
| constant <span class="predefined-type">float</span> *filter_weights, |
| read_only image2d_t src_image, |
| write_only image2d_t dst_image) |
| { |
| ... |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Argument index values for <code>image_filter</code> will be 0 for <code>n</code>, 1 for <code>m</code>, 2 for |
| <code>filter_weights</code>, 3 for <code>src_image</code> and 4 for <code>dst_image</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>arg_size</em> specifies the size of the argument value. |
| If the argument is a memory object, the size is the size of the memory |
| object. |
| For arguments declared with the <code>local</code> qualifier, the size specified will |
| be the size in bytes of the buffer that must be allocated for the <code>local</code> |
| argument. |
| If the argument is of type <em>sampler_t</em>, the <em>arg_size</em> value must be equal |
| to <code>sizeof(cl_sampler)</code>. |
| If the argument is of type <em>queue_t</em>, the <em>arg_size</em> value must be equal to |
| <code>sizeof(cl_command_queue)</code>. |
| For all other arguments, the size will be the size of argument type.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>arg_value</em> is a pointer to data that should be used as the argument value |
| for argument specified by <em>arg_index</em>. |
| The argument data pointed to by <em>arg_value</em> is copied and the <em>arg_value</em> |
| pointer can therefore be reused by the application after <strong>clSetKernelArg</strong> |
| returns. |
| The argument value specified is the value used by all API calls that enqueue |
| <em>kernel</em> (<strong>clEnqueueNDRangeKernel</strong>) until the argument value is changed by a |
| call to <strong>clSetKernelArg</strong> for <em>kernel</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the argument is a memory object (buffer, pipe, image or image array), the |
| <em>arg_value</em> entry will be a pointer to the appropriate buffer, pipe, image |
| or image array object. |
| The memory object must be created with the context associated with the |
| kernel object. |
| If the argument is a buffer object, the <em>arg_value</em> pointer can be <code>NULL</code> or |
| point to a <code>NULL</code> value in which case a <code>NULL</code> value will be used as the |
| value for the argument declared as a pointer to <code>global</code> or <code>constant</code> |
| memory in the kernel. |
| If the argument is declared with the <code>local</code> qualifier, the <em>arg_value</em> |
| entry must be <code>NULL</code>. |
| If the argument is of type <em>sampler_t</em>, the <em>arg_value</em> entry must be a |
| pointer to the sampler object. |
| If the argument is of type <em>queue_t</em>, the <em>arg_value</em> entry must be a |
| pointer to the device queue object.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the argument is declared to be a pointer of a built-in scalar or vector |
| type, or a user defined structure type in the global or constant address |
| space, the memory object specified as argument value must be a buffer object |
| (or <code>NULL</code>). |
| If the argument is declared with the <code>constant</code> qualifier, the size in bytes |
| of the memory object cannot exceed CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE and |
| the number of arguments declared as pointers to <code>constant</code> memory cannot |
| exceed CL_DEVICE_MAX_CONSTANT_ARGS.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The memory object specified as argument value must be a pipe object if the |
| argument is declared with the <em>pipe</em> qualifier.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The memory object specified as argument value must be a 2D image object if |
| the argument is declared to be of type <em>image2d_t</em>. |
| The memory object specified as argument value must be a 2D image object with |
| image channel order = CL_DEPTH if the argument is declared to be of type |
| <em>image2d_depth_t</em>. |
| The memory object specified as argument value must be a 3D image object if |
| argument is declared to be of type <em>image3d_t</em>. |
| The memory object specified as argument value must be a 1D image object if |
| the argument is declared to be of type <em>image1d_t</em>. |
| The memory object specified as argument value must be a 1D image buffer |
| object if the argument is declared to be of type <em>image1d_buffer_t</em>. |
| The memory object specified as argument value must be a 1D image array |
| object if argument is declared to be of type <em>image1d_array_t</em>. |
| The memory object specified as argument value must be a 2D image array |
| object if argument is declared to be of type <em>image2d_array_t</em>. |
| The memory object specified as argument value must be a 2D image array |
| object with image channel order = CL_DEPTH if argument is declared to be of |
| type <em>image2d_array_depth_t</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For all other kernel arguments, the <em>arg_value</em> entry must be a pointer to |
| the actual data to be used as argument value.</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="paragraph"> |
| <p>A kernel object does not update the reference count for objects such as |
| memory or sampler objects specified as argument values by <strong>clSetKernelArg</strong>. |
| Users may not rely on a kernel object to retain objects specified as |
| argument values to the kernel.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Implementations shall not allow cl_kernel objects to hold reference |
| counts to cl_kernel arguments, because no mechanism is provided for the |
| user to tell the kernel to release that ownership right. |
| If the kernel holds ownership rights on kernel args, that would make it |
| impossible for the user to tell with certainty when he may safely |
| release user allocated resources associated with OpenCL objects such as |
| the cl_mem backing store used with CL_MEM_USE_HOST_PTR.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clSetKernelArg</strong> returns CL_SUCCESS if the function was executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_KERNEL if <em>kernel</em> is not a valid kernel object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_ARG_INDEX if <em>arg_index</em> is not a valid argument index.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_ARG_VALUE if <em>arg_value</em> specified is not a valid value.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT for an argument declared to be a memory object |
| when the specified <em>arg_value</em> is not a valid memory object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_SAMPLER for an argument declared to be of type <em>sampler_t</em> |
| when the specified <em>arg_value</em> is not a valid sampler object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_DEVICE_QUEUE for an argument declared to be of type <em>queue_t</em> |
| when the specified <em>arg_value</em> is not a valid device queue object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_ARG_SIZE if <em>arg_size</em> does not match the size of the data |
| type for an argument that is not a memory object or if the argument is a |
| memory object and <em>arg_size</em> != <code>sizeof(cl_mem)</code> or if <em>arg_size</em> is |
| zero and the argument is declared with the local qualifier or if the |
| argument is a sampler and <em>arg_size</em> != <code>sizeof(cl_sampler)</code>.</p> |
| </li> |
| <li> |
| <p>CL_MAX_SIZE_RESTRICTION_EXCEEDED if the size in bytes of the memory |
| object (if the argument was declared with constant qualifier) or |
| <em>arg_size</em> (if the argument was declared with local qualifier) exceed |
| the maximum size restriction that was set with the optional language |
| attribute. |
| The optional attribute can be <code>cl::max_size</code> defined in OpenCL 2.2 C++ |
| Kernel Language specification or <code>SpvDecorationMaxByteOffset</code> defined |
| in SPIR-V 1.2 Specification.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_ARG_VALUE if the argument is an image declared with the |
| <code>read_only</code> qualifier and <em>arg_value</em> refers to an image object created |
| with <em>cl_mem_flags</em> of CL_MEM_WRITE_ONLY or if the image argument is |
| declared with the <code>write_only</code> qualifier and <em>arg_value</em> refers to an |
| image object created with <em>cl_mem_flags</em> of CL_MEM_READ_ONLY.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clSetKernelArgSVMPointer(cl_kernel kernel, |
| cl_uint arg_index, |
| <span class="directive">const</span> <span class="directive">void</span> *arg_value)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>is used to set a SVM pointer as the argument value for a specific argument |
| of a kernel.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>kernel</em> is a valid kernel object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>arg_index</em> is the argument index. |
| Arguments to the kernel are referred by indices that go from 0 for the |
| leftmost argument to <em>n</em> - 1, where <em>n</em> is the total number of arguments |
| declared by a kernel.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>arg_value</em> is the SVM pointer that should be used as the argument value for |
| argument specified by <em>arg_index</em>. |
| The SVM pointer specified is the value used by all API calls that enqueue |
| <em>kernel</em> (<strong>clEnqueueNDRangeKernel</strong>) until the argument value is changed by a |
| call to <strong>clSetKernelArgSVMPointer</strong> for <em>kernel</em>. |
| The SVM pointer can only be used for arguments that are declared to be a |
| pointer to <code>global</code> or <code>constant</code> memory. |
| The SVM pointer value must be aligned according to the arguments type. |
| For example, if the argument is declared to be <code>global float4 *p</code>, the SVM |
| pointer value passed for <code>p</code> must be at a minimum aligned to a <code>float4</code>. |
| The SVM pointer value specified as the argument value can be the pointer |
| returned by <strong>clSVMAlloc</strong> or can be a pointer offset into the SVM region.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clSetKernelArgSVMPointer</strong> returns CL_SUCCESS if the function was executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_KERNEL if <em>kernel</em> is not a valid kernel object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_ARG_INDEX if <em>arg_index</em> is not a valid argument index.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_ARG_VALUE if <em>arg_value</em> specified is not a valid value.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clSetKernelExecInfo(cl_kernel kernel, |
| cl_kernel_exec_info param_name, |
| size_t param_value_size, |
| <span class="directive">const</span> <span class="directive">void</span> *param_value)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>can be used to pass additional information other than argument values to a |
| kernel.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>kernel</em> specifies the kernel object being queried.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_name</em> specifies the information to be passed to kernel. |
| The list of supported <em>param_name</em> types and the corresponding values passed |
| in <em>param_value</em> is described in the <a href="#kernel-exec-info-table">Kernel |
| Execution Properties</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size</em> specifies the size in bytes of the memory pointed to by |
| <em>param_value</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value</em> is a pointer to memory where the appropriate values determined |
| by <em>param_name</em> are specified.</p> |
| </div> |
| <table id="kernel-exec-info-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 28. <strong>clSetKernelExecInfo_</strong> parameter values</caption> |
| <colgroup> |
| <col style="width: 34%;"> |
| <col style="width: 33%;"> |
| <col style="width: 33%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_kernel_exec_info</strong></th> |
| <th class="tableblock halign-left valign-top">Type</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_EXEC_INFO_SVM_PTRS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">void *[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">SVM pointers must reference locations contained entirely within |
| buffers that are passed to kernel as arguments, or that are passed |
| through the execution information.</p> |
| <p class="tableblock"> Non-argument SVM buffers must be specified by passing pointers to |
| those buffers via <strong>clSetKernelExecInfo</strong> for coarse-grain and |
| fine-grain buffer SVM allocations but not for finegrain system SVM |
| allocations.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This flag indicates whether the kernel uses pointers that are fine |
| grain system SVM allocations. |
| These fine grain system SVM pointers may be passed as arguments or |
| defined in SVM buffers that are passed as arguments to <em>kernel</em>.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p><strong>clSetKernelExecInfo</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_KERNEL if <em>kernel</em> is a not a valid kernel object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is not valid, if <em>param_value</em> is |
| <code>NULL</code> or if the size specified by <em>param_value_size</em> is not valid.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if <em>param_name</em> = |
| CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM and <em>param_value</em> = CL_TRUE |
| but no devices in context associated with <em>kernel</em> support fine-grain |
| system SVM allocations.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>Coarse-grain or fine-grain buffer SVM pointers used by a kernel which |
| are not passed as a kernel arguments must be specified using |
| <strong>clSetKernelExecInfo</strong> with CL_KERNEL_EXEC_INFO_SVM_PTRS. |
| For example, if SVM buffer A contains a pointer to another SVM buffer B, |
| and the kernel dereferences that pointer, then a pointer to B must |
| either be passed as an argument in the call to that kernel or it must be |
| made available to the kernel using <strong>clSetKernelExecInfo</strong>. |
| For example, we might pass extra SVM pointers as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">clSetKernelExecInfo(kernel, |
| CL_KERNEL_EXEC_INFO_SVM_PTRS, |
| num_ptrs * <span class="keyword">sizeof</span>(<span class="directive">void</span> *), |
| extra_svm_ptr_list);</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Here <code>num_ptrs</code> specifies the number of additional SVM pointers while |
| <code>extra_svm_ptr_list</code> specifies a pointer to memory containing those SVM |
| pointers.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When calling <strong>clSetKernelExecInfo</strong> with CL_KERNEL_EXEC_INFO_SVM_PTRS to |
| specify pointers to non-argument SVM buffers as extra arguments to a kernel, |
| each of these pointers can be the SVM pointer returned by <strong>clSVMAlloc</strong> or |
| can be a pointer + offset into the SVM region. |
| It is sufficient to provide one pointer for each SVM buffer used.</p> |
| </div> |
| <div class="paragraph"> |
| <p>CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM is used to indicate whether |
| SVM pointers used by a kernel will refer to system allocations or not.</p> |
| </div> |
| <div class="paragraph"> |
| <p>CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM = CL_FALSE indicates that the |
| OpenCL implementation may assume that system pointers are not passed as |
| kernel arguments and are not stored inside SVM allocations passed as kernel |
| arguments.</p> |
| </div> |
| <div class="paragraph"> |
| <p>CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM = CL_TRUE indicates that the |
| OpenCL implementation must assume that system pointers might be passed as |
| kernel arguments and/or stored inside SVM allocations passed as kernel |
| arguments. |
| In this case, if the device to which the kernel is enqueued does not support |
| system SVM pointers, <strong>clEnqueueNDRangeKernel</strong> will return a |
| CL_INVALID_OPERATION error. |
| If none of the devices in the context associated with kernel support |
| fine-grain system SVM allocations, <strong>clSetKernelExecInfo</strong> will return a |
| CL_INVALID_OPERATION error.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <strong>clSetKernelExecInfo</strong> has not been called with a value for |
| <strong>CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM</strong>, the default value is used for |
| this kernel attribute. |
| The default value depends on whether the device on which the kernel is |
| enqueued supports fine-grain system SVM allocations. |
| If so, the default value used is CL_TRUE (system pointers might be passed); |
| otherwise, the default is CL_FALSE.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A call to <strong>clSetKernelExecInfo</strong> for a given value of <em>param_name</em> |
| replaces any prior value passed for that value of <em>param_name</em>. |
| Only one <em>param_value</em> will be stored for each value of <em>param_name</em>.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_copying_kernel_objects">5.9.3. Copying Kernel Objects</h4> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_kernel clCloneKernel(cl_kernel source_kernel, |
| cl_int *errcode_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>is used to make a shallow copy of the kernel object, its arguments and any |
| information passed to the kernel object using <strong>clSetKernelExecInfo</strong>. |
| If the kernel object was ready to be enqueued before copying it, the clone |
| of the kernel object is ready to enqueue.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>source_kernel</em> is a valid cl_kernel object that will be copied. |
| <em>source_kernel</em> will not be modified in any way by this function.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>errcode_ret</em> will be assigned an appropriate error code. |
| If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCloneKernel</strong> returns a valid non-zero kernel object and <em>errcode_ret</em> is |
| set to CL_SUCCESS if the kernel is successfully copied. |
| Otherwise it returns a <code>NULL</code> value with one of the following error values |
| returned in <em>errcode_ret</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_KERNEL if <em>kernel</em> is not a valid kernel object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The returned kernel object is an exact copy of <em>source_kernel</em>, with one |
| caveat: the reference count on the returned kernel object is set as if it |
| had been returned by <strong>clCreateKernel</strong>. |
| The reference count of <em>source_kernel will</em> not be changed.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The resulting kernel will be in the same state as if <strong>clCreateKernel</strong> is |
| called to create the resultant kernel with the same arguments as those used |
| to create <em>source_kernel</em>, the latest call to <strong>clSetKernelArg</strong> or |
| <strong>clSetKernelArgSVMPointer</strong> for each argument index applied to kernel and the |
| last call to <strong>clSetKernelExecInfo</strong> for each value of the param name |
| parameter are applied to the new kernel object.</p> |
| </div> |
| <div class="paragraph"> |
| <p>All arguments of the new kernel object must be intact and it may be |
| correctly used in the same situations as kernel except those that assume a |
| pre-existing reference count. |
| Setting arguments on the new kernel object will not affect <em>source_kernel</em> |
| except insofar as the argument points to a shared underlying entity and in |
| that situation behavior is as if two kernel objects had been created and the |
| same argument applied to each. |
| Only the data stored in the kernel object is copied; data referenced by the |
| kernels arguments are not copied. |
| For example, if a buffer or pointer argument is set on a kernel object, the |
| pointer is copied but the underlying memory allocation is not.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_kernel_object_queries">5.9.4. Kernel Object Queries</h4> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetKernelInfo(cl_kernel kernel, |
| cl_kernel_info param_name, |
| size_t param_value_size, |
| <span class="directive">void</span> *param_value, |
| size_t *param_value_size_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>returns information about the kernel object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>kernel</em> specifies the kernel object being queried.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_name</em> specifies the information to query. |
| The list of supported <em>param_name</em> types and the information returned in |
| <em>param_value</em> by <strong>clGetKernelInfo</strong> is described in the |
| <a href="#kernel-info-table">Kernel Object Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value</em> is a pointer to memory where the appropriate result being |
| queried is returned. |
| If <em>param_value</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to |
| by <em>param_value</em>. |
| This size must be ≥ size of return type as described in the |
| <a href="#kernel-info-table">Kernel Object Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size_ret</em> returns the actual size in bytes of data being |
| queried by <em>param_name</em>. |
| If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <table id="kernel-info-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 29. <strong>clGetKernelInfo</strong> parameter queries</caption> |
| <colgroup> |
| <col style="width: 34%;"> |
| <col style="width: 33%;"> |
| <col style="width: 33%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_kernel_info</strong></th> |
| <th class="tableblock halign-left valign-top">Return Type</th> |
| <th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_FUNCTION_NAME</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the kernel function name.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_NUM_ARGS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the number of arguments to kernel.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_REFERENCE_COUNT</strong><sup>16</sup></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the <em>kernel</em> reference count.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_CONTEXT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_context</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the context associated with <em>kernel</em>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_PROGRAM</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_program</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the program object associated with kernel.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_ATTRIBUTES</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns any attributes specified using the <code>__attribute__</code> |
| OpenCL C qualifier (or using an OpenCL C++ qualifier syntax [[]] ) |
| with the kernel function declaration in the program source. |
| These attributes include attributes described in the earlier OpenCL |
| C kernel language specifications and other attributes supported by |
| an implementation.</p> |
| <p class="tableblock"> Attributes are returned as they were declared inside |
| <code>__attribute__((...))</code>, with any surrounding whitespace and |
| embedded newlines removed. |
| When multiple attributes are present, they are returned as a single, |
| space delimited string.</p> |
| <p class="tableblock"> For kernels not created from OpenCL C source and the |
| <strong>clCreateProgramWithSource</strong> API call the string returned from this |
| query will be empty.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">16</dt> |
| <dd> |
| <p>The reference count returned should be considered immediately stale. |
| It is unsuitable for general use in applications. |
| This feature is provided for identifying memory leaks.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clGetKernelInfo</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes |
| specified by <em>param_value_size</em> is < size of return type as described in |
| the <a href="#kernel-info-table">Kernel Object Queries</a> table and <em>param_value</em> |
| is not <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_KERNEL if <em>kernel</em> is a not a valid kernel object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetKernelWorkGroupInfo(cl_kernel kernel, |
| cl_device_id device, |
| cl_kernel_work_group_info param_name, |
| size_t param_value_size, |
| <span class="directive">void</span> *param_value, |
| size_t *param_value_size_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>returns information about the kernel object that may be specific to a |
| device.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>kernel</em> specifies the kernel object being queried.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>device</em> identifies a specific device in the list of devices associated with |
| <em>kernel</em>. |
| The list of devices is the list of devices in the OpenCL context that is |
| associated with <em>kernel</em>. |
| If the list of devices associated with <em>kernel</em> is a single device, <em>device</em> |
| can be a <code>NULL</code> value.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_name</em> specifies the information to query. |
| The list of supported <em>param_name</em> types and the information returned in |
| <em>param_value</em> by <strong>clGetKernelWorkGroupInfo</strong> is described in the |
| <a href="#kernel-workgroup-info-table">Kernel Object Device Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value</em> is a pointer to memory where the appropriate result being |
| queried is returned. |
| If <em>param_value</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to |
| by <em>param_value</em>. |
| This size must be ≥ size of return type as described in the |
| <a href="#kernel-workgroup-info-table">Kernel Object Device Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size_ret</em> returns the actual size in bytes of data being |
| queried by <em>param_name</em>. |
| If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <table id="kernel-workgroup-info-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 30. <strong>clGetKernelWorkGroupInfo</strong> parameter queries</caption> |
| <colgroup> |
| <col style="width: 34%;"> |
| <col style="width: 33%;"> |
| <col style="width: 33%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_kernel_work_group_info</strong></th> |
| <th class="tableblock halign-left valign-top">Return Type</th> |
| <th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_GLOBAL_WORK_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t[3]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This provides a mechanism for the application to query the maximum |
| global size that can be used to execute a kernel (i.e. |
| <em>global_work_size</em> argument to <strong>clEnqueueNDRangeKernel</strong>) on a custom |
| device given by device or a built-in kernel on an OpenCL device |
| given by device.</p> |
| <p class="tableblock"> If device is not a custom device and kernel is not a built-in |
| kernel, <strong>clGetKernelWorkGroupInfo</strong> returns the error |
| CL_INVALID_VALUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_WORK_GROUP_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This provides a mechanism for the application to query the maximum |
| workgroup size that can be used to execute the kernel on a specific |
| device given by device. |
| The OpenCL implementation uses the resource requirements of the |
| kernel (register usage etc.) to determine what this work-group size |
| should be.</p> |
| <p class="tableblock"> As a result and unlike CL_DEVICE_MAX_WORK_GROUP_SIZE this value may |
| vary from one kernel to another as well as one device to another.</p> |
| <p class="tableblock"> CL_KERNEL_WORK_GROUP_SIZE will be less than or equal to |
| CL_DEVICE_MAX_WORK_GROUP_SIZE for a given kernel object.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_COMPILE_WORK_GROUP_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t[3]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the work-group size specified in the kernel source or IL.</p> |
| <p class="tableblock"> If the work-group size is not specified in the kernel source or IL, |
| (0, 0, 0) is returned.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_LOCAL_MEM_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the amount of local memory in bytes being used by a kernel. |
| This includes local memory that may be needed by an implementation |
| to execute the kernel, variables declared inside the kernel with the |
| <code>__local</code> address qualifier and local memory to be allocated for |
| arguments to the kernel declared as pointers with the <code>__local</code> |
| address qualifier and whose size is specified with <strong>clSetKernelArg</strong>.</p> |
| <p class="tableblock"> If the local memory size, for any pointer argument to the kernel |
| declared with the <code>__local</code> address qualifier, is not specified, |
| its size is assumed to be 0.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the preferred multiple of work-group size for launch. |
| This is a performance hint. |
| Specifying a work-group size that is not a multiple of the value |
| returned by this query as the value of the local work size argument |
| to <strong>clEnqueueNDRangeKernel</strong> will not fail to enqueue the kernel for |
| execution unless the work-group size specified is larger than the |
| device maximum.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_PRIVATE_MEM_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the minimum amount of private memory, in bytes, used by each |
| work-item in the kernel. |
| This value may include any private memory needed by an |
| implementation to execute the kernel, including that used by the |
| language built-ins and variable declared inside the kernel with the |
| <code>__private</code> qualifier.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p><strong>clGetKernelWorkGroupInfo</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_DEVICE if <em>device</em> is not in the list of devices associated |
| with <em>kernel</em> or if <em>device</em> is <code>NULL</code> but there is more than one device |
| associated with <em>kernel</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes |
| specified by <em>param_value_size</em> is < size of return type as described in |
| the <a href="#kernel-workgroup-info-table">Kernel Object Device Queries</a> table |
| and <em>param_value</em> is not <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is CL_KERNEL_GLOBAL_WORK_SIZE and |
| <em>device</em> is not a custom device and <em>kernel</em> is not a built-in kernel.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_KERNEL if <em>kernel</em> is a not a valid kernel object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetKernelSubGroupInfo(cl_kernel kernel, |
| cl_device_id device, |
| cl_kernel_sub_group_info param_name, |
| size_t input_value_size, |
| <span class="directive">const</span> <span class="directive">void</span> *input_value, |
| size_t param_value_size, |
| <span class="directive">void</span> *param_value, |
| size_t *param_value_size_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>returns information about the kernel object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>kernel</em> specifies the kernel object being queried.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>device</em> identifies a specific device in the list of devices associated with |
| <em>kernel</em>. |
| The list of devices is the list of devices in the OpenCL context that is |
| associated with <em>kernel</em>. |
| If the list of devices associated with <em>kernel</em> is a single device, <em>device</em> |
| can be a <code>NULL</code> value.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_name</em> specifies the information to query. |
| The list of supported <em>param_name</em> types and the information returned in |
| <em>param_value</em> by <strong>clGetKernelSubGroupInfo</strong> is described in the |
| <a href="#kernel-subgroup-info-table">Kernel Object Subgroup Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>input_value_size</em> is used to specify the size in bytes of memory pointed to |
| by <em>input_value</em>. |
| This size must be == size of input type as described in the table below.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>input_value</em> is a pointer to memory where the appropriate parameterization |
| of the query is passed from. |
| If <em>input_value</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value</em> is a pointer to memory where the appropriate result being |
| queried is returned. |
| If <em>param_value</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to |
| by <em>param_value</em>. |
| This size must be ≥ size of return type as described in the |
| <a href="#kernel-subgroup-info-table">Kernel Object Subgroup Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size_ret</em> returns the actual size in bytes of data being |
| queried by <em>param_name</em>. |
| If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <table id="kernel-subgroup-info-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 31. <strong>clGetKernelSubGroupInfo</strong> parameter queries</caption> |
| <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"><strong>cl_kernel_sub_group_info</strong></th> |
| <th class="tableblock halign-left valign-top">Input Type</th> |
| <th class="tableblock halign-left valign-top">Return Type</th> |
| <th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t *</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the maximum sub-group size for this kernel. |
| All sub-groups must be the same size, while the last subgroup in |
| any work-group (i.e. the subgroup with the maximum index) could |
| be the same or smaller size.</p> |
| <p class="tableblock"> The <em>input_value</em> must be an array of size_t values |
| corresponding to the local work size parameter of the intended |
| dispatch. |
| The number of dimensions in the ND-range will be inferred from |
| the value specified for <em>input_value_size</em>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t *</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of sub-groups that will be present in each |
| work-group for a given local work size. |
| All workgroups, apart from the last work-group in each dimension |
| in the presence of non-uniform work-group sizes, will have the |
| same number of sub-groups.</p> |
| <p class="tableblock"> The <em>input_value</em> must be an array of size_t values |
| corresponding to the local work size parameter of the intended |
| dispatch. |
| The number of dimensions in the ND-range will be inferred from |
| the value specified for <em>input_value_size</em>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the local size that will generate the requested number |
| of sub-groups for the kernel. |
| The output array must be an array of size_t values corresponding |
| to the local size parameter. |
| Any returned work-group will have one dimension. |
| Other dimensions inferred from the value specified for |
| param_value_size will be filled with the value 1. |
| The returned value will produce an exact number of sub-groups |
| and result in no partial groups for an executing kernel except |
| in the case where the last work-group in a dimension has a size |
| different from that of the other groups. |
| If no work-group size can accommodate the requested number of |
| sub-groups, 0 will be returned in each element of the return |
| array.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_MAX_NUM_SUB_GROUPS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">ignored</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">This provides a mechanism for the application to query the |
| maximum number of sub-groups that may make up each work-group to |
| execute a kernel on a specific device given by device. |
| The OpenCL implementation uses the resource requirements of the |
| kernel (register usage etc.) to determine what this work-group |
| size should be. |
| The returned value may be used to compute a work-group size to |
| enqueue the kernel with to give a round number of sub-groups for |
| an enqueue.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_COMPILE_NUM_SUB_GROUPS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">ignored</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of sub-groups specified in the kernel source |
| or IL. If the sub-group count is not specified then 0 is returned.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p><strong>clGetKernelSubGroupInfo</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_DEVICE if <em>device</em> is not in the list of devices associated |
| with <em>kernel</em> or if <em>device</em> is <code>NULL</code> but there is more than one device |
| associated with <em>kernel</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes |
| specified by <em>param_value_size</em> is < size of return type as described in |
| the <a href="#kernel-subgroup-info-table">Kernel Object Subgroup Queries</a> table |
| and <em>param_value</em> is not <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is |
| CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE and the size in bytes specified by |
| <em>input_value_size</em> is not valid or if <em>input_value</em> is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_KERNEL if <em>kernel</em> is a not a valid kernel object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetKernelArgInfo(cl_kernel kernel, |
| cl_uint arg_indx, |
| cl_kernel_arg_info param_name, |
| size_t param_value_size, |
| <span class="directive">void</span> *param_value, |
| size_t *param_value_size_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>returns information about the arguments of a kernel.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Kernel argument information is only available if the program object |
| associated with <em>kernel</em> is created with <strong>clCreateProgramWithSource</strong> and the |
| program executable was built with the <code>-cl-kernel-arg-info option</code> specified |
| in options argument to <strong>clBuildProgram</strong> or <strong>clCompileProgram</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>kernel</em> specifies the kernel object being queried.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>arg_indx</em> is the argument index. |
| Arguments to the kernel are referred by indices that go from 0 for the |
| leftmost argument to <em>n</em> - 1, where <em>n</em> is the total number of arguments |
| declared by a kernel.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_name</em> specifies the argument information to query. |
| The list of supported <em>param_name</em> types and the information returned in |
| <em>param_value</em> by <strong>clGetKernelArgInfo</strong> is described in the |
| <a href="#kernel-argument-info-table">Kernel Argument Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value</em> is a pointer to memory where the appropriate result being |
| queried is returned. |
| If <em>param_value</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to |
| by <em>param_value</em>. |
| This size must be > size of return type as described in the |
| <a href="#kernel-argument-info-table">Kernel Argument Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size ret</em> returns the actual size in bytes of data being |
| queried by <em>param_name</em>. |
| If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <table id="kernel-argument-info-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 32. <strong>clGetKernelArgInfo</strong> parameter queries</caption> |
| <colgroup> |
| <col style="width: 34%;"> |
| <col style="width: 33%;"> |
| <col style="width: 33%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_kernel_arg_info</strong></th> |
| <th class="tableblock halign-left valign-top">Return Type</th> |
| <th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_ARG_ADDRESS_QUALIFIER</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_kernel_arg_address_qualifier</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the address qualifier specified for the argument given by |
| <em>arg_indx</em>. |
| This can be one of the following values:</p> |
| <p class="tableblock"> CL_KERNEL_ARG_ADDRESS_GLOBAL<br> |
| CL_KERNEL_ARG_ADDRESS_LOCAL<br> |
| CL_KERNEL_ARG_ADDRESS_CONSTANT<br> |
| CL_KERNEL_ARG_ADDRESS_PRIVATE</p> |
| <p class="tableblock"> If no address qualifier is specified, the default address qualifier |
| which is CL_KERNEL_ARG_ADDRESS_PRIVATE is returned.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_ARG_ACCESS_QUALIFIER</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_kernel_arg_access_qualifier</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the access qualifier specified for the argument given by |
| <em>arg_indx</em>. |
| This can be one of the following values:</p> |
| <p class="tableblock"> CL_KERNEL_ARG_ACCESS_READ_ONLY<br> |
| CL_KERNEL_ARG_ACCESS_WRITE_ONLY<br> |
| CL_KERNEL_ARG_ACCESS_READ_WRITE<br> |
| CL_KERNEL_ARG_ACCESS_NONE</p> |
| <p class="tableblock"> If argument is not an image type and is not declared with the pipe |
| qualifier, CL_KERNEL_ARG_ACCESS_NONE is returned. |
| If argument is an image type, the access qualifier specified or the |
| default access qualifier is returned.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_ARG_TYPE_NAME</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the type name specified for the argument given by |
| <em>arg_indx</em>. |
| The type name returned will be the argument type name as it was |
| declared with any whitespace removed. |
| If argument type name is an unsigned scalar type (i.e. unsigned |
| char, unsigned short, unsigned int, unsigned long), uchar, ushort, |
| uint and ulong will be returned. |
| The argument type name returned does not include any type |
| qualifiers.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_ARG_TYPE_QUALIFIER</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_kernel_arg_type_qualifier</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the type qualifier specified for the argument given by |
| <em>arg_indx</em>. |
| The returned value can be: CL_KERNEL_ARG_TYPE_CONST<sup>17</sup>, |
| CL_KERNEL_ARG_TYPE_RESTRICT, CL_KERNEL_ARG_TYPE_VOLATILE<sup>18</sup>, a |
| combination of the above enums, CL_KERNEL_ARG_TYPE_PIPE or |
| CL_KERNEL_ARG_TYPE_NONE.</p> |
| <p class="tableblock"> CL_KERNEL_ARG_TYPE_NONE is returned for all parameters passed by |
| value.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_ARG_NAME</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the name specified for the argument given by <em>arg_indx</em>.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">17</dt> |
| <dd> |
| <p>CL_KERNEL_ARG_TYPE_CONST is returned for |
| CL_KERNEL_ARG_TYPE_QUALIFIER if the argument is declared with the |
| <code>constant</code> address space qualifier.</p> |
| </dd> |
| <dt class="hdlist1">18</dt> |
| <dd> |
| <p>CL_KERNEL_ARG_TYPE_VOLATILE is returned for |
| CL_KERNEL_ARG_TYPE_QUALIFIER if the argument is a pointer and the |
| referenced type is declared with the volatile qualifier. |
| For example, a kernel argument declared as <code>global int volatile *x</code> |
| returns CL_KERNEL_ARG_TYPE_VOLATILE but a kernel argument declared |
| as <code>global int * volatile x</code> does not. |
| Similarly, CL_KERNEL_ARG_TYPE_CONST is returned if the argument is a |
| pointer and the referenced type is declared with the restrict or |
| const qualifier. |
| For example, a kernel argument declared as <code>global int const *x</code> |
| returns CL_KERNEL_ARG_TYPE_CONST but a kernel argument declared as |
| <code>global int * const x</code> does not. |
| CL_KERNEL_ARG_TYPE_RESTRICT will be returned if the pointer type is |
| marked <code>restrict</code>. |
| For example, <code>global int * restrict x</code> returns |
| CL_KERNEL_ARG_TYPE_RESTRICT.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clGetKernelArgInfo</strong> returns CL SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_ARG_INDEX if <em>arg_indx</em> is not a valid argument index.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes |
| specified by <em>param_value</em> size is < size of return type as described in |
| the <a href="#kernel-argument-info-table">Kernel Argument Queries</a> table and |
| <em>param_value</em> is not <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_KERNEL_ARG_INFO_NOT_AVAILABLE if the argument information is not |
| available for kernel.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_KERNEL if <em>kernel</em> is a not a valid kernel object.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_executing_kernels">5.10. Executing Kernels</h3> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueNDRangeKernel(cl_command_queue command_queue, |
| cl_kernel kernel, |
| cl_uint work_dim, |
| <span class="directive">const</span> size_t *global_work_offset, |
| <span class="directive">const</span> size_t *global_work_size, |
| <span class="directive">const</span> size_t *local_work_size, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a command to execute a kernel on a device.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> is a valid host command-queue. |
| The kernel will be queued for execution on the device associated with |
| <em>command_queue</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>kernel</em> is a valid kernel object. |
| The OpenCL context associated with <em>kernel</em> and <em>command-queue</em> must be the |
| same.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>work_dim</em> is the number of dimensions used to specify the global work-items |
| and work-items in the work-group. |
| <em>work_dim</em> must be greater than zero and less than or equal to |
| CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS. |
| If <em>global_work_size</em> is <code>NULL</code>, or the value in any passed dimension is 0 |
| then the kernel command will trivially succeed after its event dependencies |
| are satisfied and subsequently update its completion event. |
| The behavior in this situation is similar to that of an enqueued marker, |
| except that unlike a marker, an enqueued kernel with no events passed to |
| <em>event_wait_list</em> may run at any time.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>global_work_offset</em> can be used to specify an array of <em>work_dim</em> unsigned |
| values that describe the offset used to calculate the global ID of a |
| work-item. |
| If <em>global_work_offset</em> is <code>NULL</code>, the global IDs start at offset (0, 0, 0).</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>global_work_size</em> points to an array of <em>work_dim</em> unsigned values that |
| describe the number of global work-items in <em>work_dim</em> dimensions that will |
| execute the kernel function. |
| The total number of global work-items is computed as <em>global_work_size</em>[0] |
| × …​ × <em>global_work_size</em>[<em>work_dim</em> - 1].</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>local_work_size</em> points to an array of <em>work_dim</em> unsigned values that |
| describe the number of work-items that make up a work-group (also referred |
| to as the size of the work-group) that will execute the kernel specified by |
| <em>kernel</em>. |
| The total number of work-items in a work-group is computed as |
| <em>local_work_size</em>[0] × …​ × <em>local_work_size</em>[<em>work_dim</em> - 1]. |
| The total number of work-items in the work-group must be less than or equal |
| to the CL_KERNEL_WORK_GROUP_SIZE value specified in the |
| <a href="#kernel-workgroup-info-table">Kernel Object Device Queries</a> table, and the |
| number of work-items specified in <em>local_work_size</em>[0], …​, |
| <em>local_work_size</em>[<em>work_dim</em> - 1] must be less than or equal to the |
| corresponding values specified by CL_DEVICE_MAX_WORK_ITEM_SIZES[0], …​, |
| CL_DEVICE_MAX_WORK_ITEM_SIZES[<em>work_dim</em> - 1]. |
| The explicitly specified <em>local_work_size</em> will be used to determine how to |
| break the global work-items specified by <em>global_work_size</em> into appropriate |
| work-group instances.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Enabling non-uniform work-groups requires the <em>kernel</em>'s program to be |
| compiled without the <code>-cl-uniform-work-group-size</code> flag. |
| If the program was created with <strong>clCreateProgramWithSource</strong>, non-uniform |
| work-groups are enabled only if the program was compiled with the |
| <code>-cl-std=CL2.0</code> flag and without the <code>-cl-uniform-work-group-size</code> flag. |
| If the program was created using <strong>clLinkProgram</strong> and any of the linked |
| programs were compiled in a way that only supports uniform work-group sizes, |
| the linked program only supports uniform work group sizes. |
| If <em>local_work_size</em> is specified and the OpenCL <em>kernel</em> is compiled |
| without non-uniform work-groups enabled, the values specified in |
| <em>global_work_size</em>[0], …​, <em>global_work_size</em>[<em>work_dim</em> - 1] must be |
| evenly divisible by the corresponding values specified in |
| <em>local_work_size</em>[0], …​, <em>local_work_size</em>[<em>work_dim</em> - 1].</p> |
| </div> |
| <div class="paragraph"> |
| <p>If non-uniform work-groups are enabled for the kernel, any single dimension |
| for which the global size is not divisible by the local size will be |
| partitioned into two regions. |
| One region will have work-groups that have the same number of work items as |
| was specified by the local size parameter in that dimension. |
| The other region will have work-groups with less than the number of work |
| items specified by the local size parameter in that dimension. |
| The global IDs and group IDs of the work items in the first region will be |
| numerically lower than those in the second, and the second region will be at |
| most one work-group wide in that dimension. |
| Work-group sizes could be non-uniform in multiple dimensions, potentially |
| producing work-groups of up to 4 different sizes in a 2D range and 8 |
| different sizes in a 3D range.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>local_work_size</em> is <code>NULL</code> and the kernel is compiled without support |
| for non-uniform work-groups, the OpenCL runtime will implement the ND-range |
| with uniform work-group sizes. |
| If <em>local_work_size</em> is <code>NULL</code> and non-uniform-work-groups are enabled, the |
| OpenCL runtime is free to implement the ND-range using uniform or |
| non-uniform work-group sizes, regardless of the divisibility of the global |
| work size. |
| If the ND-range is implemented using non-uniform work-group sizes, the |
| work-group sizes, global IDs and group IDs will follow the same pattern as |
| described in above paragraph.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The work-group size to be used for <em>kernel</em> can also be specified in the |
| program source or intermediate language. |
| In this case the size of work group specified by <em>local_work_size</em> must |
| match the value specified in the program source.</p> |
| </div> |
| <div class="paragraph"> |
| <p>These work-group instances are executed in parallel across multiple compute |
| units or concurrently on the same compute unit.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Each work-item is uniquely identified by a global identifier. |
| The global ID, which can be read inside the kernel, is computed using the |
| value given by <em>global_work_size</em> and <em>global_work_offset</em>. |
| In addition, a work-item is also identified within a work-group by a unique |
| local ID. |
| The local ID, which can also be read by the kernel, is computed using the |
| value given by <em>local_work_size</em>. |
| The starting local ID is always (0, 0, …​, 0).</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed. |
| If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait |
| on any event to complete. |
| If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular |
| kernel-instance. |
| Event objects are unique and can be used to identify a particular |
| kernel-instance later on. |
| If <em>event</em> is <code>NULL</code>, no event will be created for this kernel-instance and |
| therefore it will not be possible for the application to query or queue a |
| wait for this particular kernel-instance. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueNDRangeKernel</strong> returns CL_SUCCESS if the kernel-instance was |
| successfully queued. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_PROGRAM_EXECUTABLE if there is no successfully built program |
| executable available for device associated with <em>command_queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_KERNEL if <em>kernel</em> is not a valid kernel object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and |
| <em>kernel</em> are not the same or if the context associated with |
| <em>command_queue</em> and events in <em>event_wait_list</em> are not the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_KERNEL_ARGS if the kernel argument values have not been |
| specified or if a kernel argument declared to be a pointer to a type |
| does not point to a named address space.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_WORK_DIMENSION if <em>work_dim</em> is not a valid value (i.e. a |
| value between 1 and 3).</p> |
| </li> |
| <li> |
| <p>CL_INVALID_GLOBAL_WORK_SIZE if any of the values specified in |
| <em>global_work_size</em>[0], …​ <em>global_work_size</em>[<em>work_dim</em> - 1] exceed the |
| maximum value representable by size_t on the device on which the |
| kernel-instance will be enqueued.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_GLOBAL_OFFSET if the value specified in <em>global_work_size</em> |
| + the corresponding values in <em>global_work_offset</em> for any |
| dimensions is greater than the maximum value representable by size t on |
| the device on which the kernel-instance will be enqueued.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_WORK_GROUP_SIZE if <em>local_work_size</em> is specified and does |
| not match the required work-group size for <em>kernel</em> in the program |
| source.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_WORK_GROUP_SIZE if <em>local_work_size</em> is specified and is not |
| consistent with the required number of sub-groups for <em>kernel</em> in the |
| program source.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_WORK_GROUP_SIZE if <em>local_work_size</em> is specified and the |
| total number of work-items in the work-group computed as |
| <em>local_work_size</em>[0] × …​ <em>local_work_size</em>[<em>work_dim</em> - 1] is |
| greater than the value specified by CL_KERNEL_WORK_GROUP_SIZE in the |
| <a href="#kernel-workgroup-info-table">Kernel Object Device Queries</a> table.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_WORK_GROUP_SIZE if the program was compiled with |
| cl-uniform-work-group-size and the number of work-items specified by |
| <em>global_work_size</em> is not evenly divisible by size of work-group given |
| by <em>local_work_size</em> or by the required work-group size specified in the |
| kernel source.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_WORK_ITEM_SIZE if the number of work-items specified in any |
| of <em>local_work_size</em>[0], …​ <em>local_work_size</em>[<em>work_dim</em> - 1] is |
| greater than the corresponding values specified by |
| CL_DEVICE_MAX_WORK_ITEM_SIZES[0], …​, |
| CL_DEVICE_MAX_WORK_ITEM_SIZES[<em>work_dim</em> - 1].</p> |
| </li> |
| <li> |
| <p>CL_MISALIGNED_SUB_BUFFER_OFFSET if a sub-buffer object is specified as |
| the value for an argument that is a buffer object and the <em>offset</em> |
| specified when the sub-buffer object is created is not aligned to |
| CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated with <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_IMAGE_SIZE if an image object is specified as an argument |
| value and the image dimensions (image width, height, specified or |
| compute row and/or slice pitch) are not supported by device associated |
| with <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_IMAGE_FORMAT_NOT_SUPPORTED if an image object is specified as an |
| argument value and the image format (image channel order and data type) |
| is not supported by device associated with <em>queue</em>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to queue the execution |
| instance of <em>kernel</em> on the command-queue because of insufficient |
| resources needed to execute the kernel. |
| For example, the explicitly specified <em>local_work_size</em> causes a failure |
| to execute the kernel because of insufficient resources such as |
| registers or local memory. |
| Another example would be the number of read-only image args used in |
| <em>kernel</em> exceed the CL_DEVICE_MAX_READ_IMAGE_ARGS value for device or |
| the number of write-only and read-write image args used in <em>kernel</em> |
| exceed the CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS value for device or the |
| number of samplers used in <em>kernel</em> exceed CL_DEVICE_MAX_SAMPLERS for |
| device.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for data store associated with image or buffer objects specified |
| as arguments to <em>kernel</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if SVM pointers are passed as arguments to a kernel |
| and the device does not support SVM or if system pointers are passed as |
| arguments to a kernel and/or stored inside SVM allocations passed as |
| kernel arguments and the device does not support fine grain system SVM |
| allocations.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueNativeKernel(cl_command_queue command_queue, |
| <span class="directive">void</span> (CL_CALLBACK *user_func)(<span class="directive">void</span> *), |
| <span class="directive">void</span> *args, |
| size_t cb_args, |
| cl_uint num_mem_objects, |
| <span class="directive">const</span> cl_mem *mem_list, |
| <span class="directive">const</span> <span class="directive">void</span> **args_mem_loc, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a command to execute a native C/C++ function not compiled using the |
| OpenCL compiler.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> is a valid host command-queue. |
| A native user function can only be executed on a command-queue created on a |
| device that has CL_EXEC_NATIVE_KERNEL capability set in |
| CL_DEVICE_EXECUTION_CAPABILITIES as specified in the |
| <a href="#device-queries-table">Device Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>user_func</em> is a pointer to a host-callable user function.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>args</em> is a pointer to the args list that <em>user_func</em> should be called with.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>cb_args</em> is the size in bytes of the args list that <em>args</em> points to.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The data pointed to by <em>args</em> and <em>cb_args</em> bytes in size will be copied and |
| a pointer to this copied region will be passed to <em>user_func</em>. |
| The copy needs to be done because the memory objects (cl_mem values) that |
| <em>args</em> may contain need to be modified and replaced by appropriate pointers |
| to global memory. |
| When <strong>clEnqueueNativeKernel</strong> returns, the memory region pointed to by <em>args</em> |
| can be reused by the application.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>num_mem_objects</em> is the number of buffer objects that are passed in <em>args</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>mem_list</em> is a list of valid buffer objects, if <em>num_mem_objects</em> > 0. |
| The buffer object values specified in <em>mem_list</em> are memory object handles |
| (cl_mem values) returned by <strong>clCreateBuffer</strong> or <code>NULL</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>args_mem_loc</em> is a pointer to appropriate locations that <em>args</em> points to |
| where memory object handles (cl_mem values) are stored. |
| Before the user function is executed, the memory object handles are replaced |
| by pointers to global memory.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em>, <em>num_events_in_wait_list</em> and <em>event</em> are as described in |
| <strong>clEnqueueNDRangeKernel</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueNativeKernel</strong> returns CL_SUCCESS if the user function execution |
| instance was successfully queued. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and events |
| in <em>event_wait_list</em> are not the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>user_func</em> is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>args</em> is a <code>NULL</code> value and <em>cb_args</em> > 0, or if |
| <em>args</em> is a <code>NULL</code> value and <em>num_mem_objects</em> > 0.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>args</em> is not <code>NULL</code> and <em>cb_args</em> is 0.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>num_mem_objects</em> > 0 and <em>mem_list</em> or |
| <em>args_mem_loc</em> are <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>num_mem_objects</em> = 0 and <em>mem_list</em> or |
| <em>args_mem_loc</em> are not <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if the device associated with <em>command_queue</em> |
| cannot execute the native kernel.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_MEM_OBJECT if one or more memory objects specified in |
| <em>mem_list</em> are not valid or are not buffer objects.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to queue the execution |
| instance of <em>kernel</em> on the command-queue because of insufficient |
| resources needed to execute the kernel.</p> |
| </li> |
| <li> |
| <p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate |
| memory for data store associated with buffer objects specified as |
| arguments to <em>kernel</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if SVM pointers are passed as arguments to a kernel |
| and the device does not support SVM or if system pointers are passed as |
| arguments to a kernel and/or stored inside SVM allocations passed as |
| kernel arguments and the device does not support fine grain system SVM |
| allocations.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>The total number of read-only images specified as arguments to a kernel |
| cannot exceed CL_DEVICE_MAX_READ_IMAGE_ARGS. |
| Each image array argument to a kernel declared with the <code>read_only</code> |
| qualifier counts as one image. |
| The total number of write-only images specified as arguments to a kernel |
| cannot exceed CL_DEVICE_MAX_WRITE_IMAGE_ARGS. |
| Each image array argument to a kernel declared with the <code>write_only</code> |
| qualifier counts as one image.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The total number of read-write images specified as arguments to a kernel |
| cannot exceed CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS. |
| Each image array argument to a kernel declared with the <code>read_write</code> |
| qualifier counts as one image.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="event-objects">5.11. Event Objects</h3> |
| <div class="paragraph"> |
| <p>Event objects can be used to refer to a kernel-instance command |
| (<strong>clEnqueueNDRangeKernel</strong>, <strong>clEnqueueNativeKernel</strong>), read, write, map and |
| copy commands on memory objects (<strong>clEnqueue{Read|Write|Map}Buffer</strong>, |
| <strong>clEnqueueUnmapMemObject</strong>, <strong>clEnqueue{Read|Write}BufferRect</strong>, |
| <strong>clEnqueue{Read|Write|Map}Image</strong>, <strong>clEnqueueCopy{Buffer|Image}</strong>, |
| <strong>clEnqueueCopyBufferRect</strong>, <strong>clEnqueueCopyBufferToImage</strong>, |
| <strong>clEnqueueCopyImageToBuffer</strong>), <strong>clEnqueueSVMMemcpy</strong>, <strong>clEnqueueSVMMemFill</strong>, |
| <strong>clEnqueueSVMMap</strong>, <strong>clEnqueueSVMUnmap</strong>, <strong>clEnqueueSVMFree</strong>, |
| <strong>clEnqueueMarkerWithWaitList</strong>, <strong>clEnqueueBarrierWithWaitList</strong> (refer to |
| <a href="#markers-barriers-waiting-for-events">Markers, Barriers and Waiting for |
| Events</a>) or user events.</p> |
| </div> |
| <div class="paragraph"> |
| <p>An event object can be used to track the execution status of a command. |
| The API calls that enqueue commands to a command-queue create a new event |
| object that is returned in the <em>event</em> argument. |
| In case of an error enqueuing the command in the command-queue the event |
| argument does not return an event object.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The execution status of an enqueued command at any given point in time can |
| be one of the following:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_QUEUED This indicates that the command has been enqueued in a |
| command-queue. |
| This is the initial state of all events except user events.</p> |
| </li> |
| <li> |
| <p>CL_SUBMITTED This is the initial state for all user events. |
| For all other events, this indicates that the command has been submitted |
| by the host to the device.</p> |
| </li> |
| <li> |
| <p>CL_RUNNING This indicates that the device has started executing this |
| command. |
| In order for the execution status of an enqueued command to change from |
| CL_SUBMITTED to CL_RUNNING, all events that this command is waiting on |
| must have completed successfully i.e. their execution status must be |
| CL_COMPLETE.</p> |
| </li> |
| <li> |
| <p>CL_COMPLETE This indicates that the command has successfully completed.</p> |
| </li> |
| <li> |
| <p>Error code The error code is a negative integer value and indicates that |
| the command was abnormally terminated. |
| Abnormal termination may occur for a number of reasons such as a bad |
| memory access.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>A command is considered to be complete if its execution status is |
| CL_COMPLETE or is a negative integer value.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the execution of a command is terminated, the command-queue associated |
| with this terminated command, and the associated context (and all other |
| command-queues in this context) may no longer be available. |
| The behavior of OpenCL API calls that use this context (and command-queues |
| associated with this context) are now considered to be |
| implementation-defined. |
| The user registered callback function specified when context is created can |
| be used to report appropriate error information.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_event clCreateUserEvent(cl_context context, |
| cl_int *errcode_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>creates a user event object. |
| User events allow applications to enqueue commands that wait on a user event |
| to finish before the command is executed by the device.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>context</em> must be a valid OpenCL context.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>errcode_ret</em> will return an appropriate error code. |
| If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clCreateUserEvent</strong> returns a valid non-zero event object and <em>errcode_ret</em> |
| is set to CL_SUCCESS if the user event object is created successfully. |
| Otherwise, it returns a <code>NULL</code> value with one of the following error values |
| returned in <em>errcode_ret</em>:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The execution status of the user event object created is set to |
| CL_SUBMITTED.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clSetUserEventStatus(cl_event event, |
| cl_int execution_status)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>sets the execution status of a user event object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> is a user event object created using <strong>clCreateUserEvent</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>execution_status</em> specifies the new execution status to be set and can be |
| CL_COMPLETE or a negative integer value to indicate an error. |
| A negative integer value causes all enqueued commands that wait on this user |
| event to be terminated. |
| <strong>clSetUserEventStatus</strong> can only be called once to change the execution |
| status of <em>event</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clSetUserEventStatus</strong> returns CL_SUCCESS if the function was executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_EVENT if <em>event</em> is not a valid user event object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if the <em>execution_status</em> is not CL_COMPLETE or a |
| negative integer value.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_OPERATION if the <em>execution_status</em> for <em>event</em> has already |
| been changed by a previous call to <strong>clSetUserEventStatus</strong>.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>If there are enqueued commands with user events in the <em>event_wait_list</em> |
| argument of <strong>clEnqueue*</strong> commands, the user must ensure that the status of |
| these user events being waited on are set using <strong>clSetUserEventStatus</strong> |
| before any OpenCL APIs that release OpenCL objects except for event objects |
| are called; otherwise the behavior is undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example, the following code sequence will result in undefined behavior |
| of <strong>clReleaseMemObject</strong>.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">ev1 = clCreateUserEvent(ctx, <span class="predefined-constant">NULL</span>); |
| clEnqueueWriteBuffer(cq, buf1, CL_FALSE, ..., <span class="integer">1</span>, &ev1, <span class="predefined-constant">NULL</span>); |
| clEnqueueWriteBuffer(cq, buf2, CL_FALSE, ...); |
| clReleaseMemObject(buf2); |
| clSetUserEventStatus(ev1, CL_COMPLETE);</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The following code sequence, however, works correctly.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">ev1 = clCreateUserEvent(ctx, <span class="predefined-constant">NULL</span>); |
| clEnqueueWriteBuffer(cq, buf1, CL_FALSE, ..., <span class="integer">1</span>, &ev1, <span class="predefined-constant">NULL</span>); |
| clEnqueueWriteBuffer(cq, buf2, CL_FALSE, ...); |
| clSetUserEventStatus(ev1, CL_COMPLETE); |
| clReleaseMemObject(buf2);</code></pre> |
| </div> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clWaitForEvents(cl_uint num_events, |
| <span class="directive">const</span> cl_event *event_list)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>waits on the host thread for commands identified by event objects in |
| <em>event_list</em> to complete. |
| A command is considered complete if its execution status is CL_COMPLETE or a |
| negative value. |
| The events specified in <em>event_list</em> act as synchronization points.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clWaitForEvents</strong> returns CL_SUCCESS if the execution status of all events |
| in <em>event_list</em> is CL_COMPLETE. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_VALUE if <em>num_events</em> is zero or <em>event_list</em> is <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if events specified in <em>event_list</em> do not belong to |
| the same context.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT if event objects specified in <em>event_list</em> are not |
| valid event objects.</p> |
| </li> |
| <li> |
| <p>CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the execution status of |
| any of the events in <em>event_list</em> is a negative integer value.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetEventInfo(cl_event event, |
| cl_event_info param_name, |
| size_t param_value_size, |
| <span class="directive">void</span> *param_value, |
| size_t *param_value_size_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>returns information about the event object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> specifies the event object being queried.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_name</em> specifies the information to query. |
| The list of supported <em>param_name</em> types and the information returned in |
| <em>param_value</em> by <strong>clGetEventInfo</strong> is described in the |
| <a href="#event-info-table">Event Object Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value</em> is a pointer to memory where the appropriate result being |
| queried is returned. |
| If <em>param_value</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to |
| by <em>param_value</em>. |
| This size must be ≥ size of return type as described in the |
| <a href="#event-info-table">Event Object Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size_ret</em> returns the actual size in bytes of data being |
| queried by <em>param_name</em>. |
| If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <table id="event-info-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 33. <strong>clGetEventInfo</strong> parameter queries</caption> |
| <colgroup> |
| <col style="width: 30%;"> |
| <col style="width: 33%;"> |
| <col style="width: 37%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_event_info</strong></th> |
| <th class="tableblock halign-left valign-top">Return Type</th> |
| <th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_EVENT_COMMAND_QUEUE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_command_queue</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the command-queue associated with <em>event</em>. |
| For user event objects, a <code>NULL</code> value is returned.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_EVENT_CONTEXT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_context</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the context associated with <em>event</em>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_EVENT_COMMAND_TYPE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_command_type</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the command associated with event. |
| Can be one of the following values:</p> |
| <p class="tableblock"> CL_COMMAND_NDRANGE_KERNEL<br> |
| CL_COMMAND_NATIVE_KERNEL<br> |
| CL_COMMAND_READ_BUFFER<br> |
| CL_COMMAND_WRITE_BUFFER<br> |
| CL_COMMAND_COPY_BUFFER<br> |
| CL_COMMAND_READ_IMAGE<br> |
| CL_COMMAND_WRITE_IMAGE<br> |
| CL_COMMAND_COPY_IMAGE<br> |
| CL_COMMAND_COPY_BUFFER_TO_IMAGE<br> |
| CL_COMMAND_COPY_IMAGE_TO_BUFFER<br> |
| CL_COMMAND_MAP_BUFFER<br> |
| CL_COMMAND_MAP_IMAGE<br> |
| CL_COMMAND_UNMAP_MEM_OBJECT<br> |
| CL_COMMAND_MARKER<br> |
| CL_COMMAND_ACQUIRE_GL_OBJECTS<br> |
| CL_COMMAND_RELEASE_GL_OBJECTS<br> |
| CL_COMMAND_READ_BUFFER_RECT<br> |
| CL_COMMAND_WRITE_BUFFER_RECT<br> |
| CL_COMMAND_COPY_BUFFER_RECT<br> |
| CL_COMMAND_USER<br> |
| CL_COMMAND_BARRIER<br> |
| CL_COMMAND_MIGRATE_MEM_OBJECTS<br> |
| CL_COMMAND_FILL_BUFFER<br> |
| CL_COMMAND_FILL_IMAGE<br> |
| CL_COMMAND_SVM_FREE<br> |
| CL_COMMAND_SVM_MEMCPY<br> |
| CL_COMMAND_SVM_MEMFILL<br> |
| CL_COMMAND_SVM_MAP<br> |
| CL_COMMAND_SVM_UNMAP</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_EVENT_COMMAND_EXECUTION_STATUS</strong><sup>19</sup></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_int</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the execution status of the command identified by event. |
| Valid values are:</p> |
| <p class="tableblock"> CL_QUEUED (command has been enqueued n the command-queue),</p> |
| <p class="tableblock"> CL_SUBMITTED (enqueued command has been submitted by the host to the |
| device associated with the command-queue),</p> |
| <p class="tableblock"> CL_RUNNING (device is currently executing this command),</p> |
| <p class="tableblock"> CL_COMPLETE (the command has completed), or</p> |
| <p class="tableblock"> Error code given by a negative integer value. (command was |
| abnormally terminated - this may be caused by a bad memory access |
| etc.). |
| These error codes come from the same set of error codes that are |
| returned from the platform or runtime API calls as return values or |
| errcode_ret values.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_EVENT_REFERENCE_COUNT</strong><sup>20</sup></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Return the <em>event</em> reference count.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">19</dt> |
| <dd> |
| <p>The error code values are negative, and event state values are positive. |
| The event state values are ordered from the largest value (CL_QUEUED) |
| for the first or initial state to the smallest value (CL_COMPLETE or |
| negative integer value) for the last or complete state. |
| The value of CL_COMPLETE and CL_SUCCESS are the same.</p> |
| </dd> |
| <dt class="hdlist1">20</dt> |
| <dd> |
| <p>The reference count returned should be considered immediately stale. |
| It is unsuitable for general use in applications. |
| This feature is provided for identifying memory leaks.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>Using <strong>clGetEventInfo</strong> to determine if a command identified by <em>event</em> has |
| finished execution (i.e. CL_EVENT_COMMAND_EXECUTION_STATUS returns |
| CL_COMPLETE) is not a synchronization point. |
| There are no guarantees that the memory objects being modified by command |
| associated with <em>event</em> will be visible to other enqueued commands.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clGetEventInfo</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes |
| specified by <em>param_value_size</em> is < size of return type as described in |
| the <a href="#kernel-argument-info-table">Kernel Argument Queries</a> table and |
| <em>param_value</em> is not <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if information to query given in <em>param_name</em> cannot be |
| queried for <em>event</em>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT if <em>event</em> is a not a valid event object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clSetEventCallback(cl_event event, |
| cl_int command_exec_callback_type, |
| <span class="directive">void</span> (CL_CALLBACK *pfn_event_notify)( |
| cl_event event, |
| cl_int event_command_exec_status, |
| <span class="directive">void</span> *user_data), |
| <span class="directive">void</span> *user_data)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>registers a user callback function for a specific command execution status. |
| The registered callback function will be called when the execution status of |
| command associated with <em>event</em> changes to an execution status equal to or |
| past the status specified by <em>command_exec_status</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Each call to <strong>clSetEventCallback</strong> registers the specified user callback |
| function on a callback stack associated with <em>event</em>. |
| The order in which the registered user callback functions are called is |
| undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> is a valid event object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_exec_callback_type</em> specifies the command execution status for |
| which the callback is registered. |
| The command execution callback values for which a callback can be registered |
| are: CL_SUBMITTED, CL_RUNNING or CL_COMPLETE<sup>21</sup>. |
| There is no guarantee that the callback functions registered for various |
| execution status values for an event will be called in the exact order that |
| the execution status of a command changes. |
| Furthermore, it should be noted that receiving a call back for an event with |
| a status other than CL_COMPLETE, in no way implies that the memory model or |
| execution model as defined by the OpenCL specification has changed. |
| For example, it is not valid to assume that a corresponding memory transfer |
| has completed unless the event is in a state CL_COMPLETE.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">21</dt> |
| <dd> |
| <p>The callback function registered for a command_exec_callback_type value |
| of CL_COMPLETE will be called when the command has completed |
| successfully or is abnormally terminated.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p><em>pfn_event_notify</em> is the event callback function that can be registered by |
| the application. |
| This callback function may be called asynchronously by the OpenCL |
| implementation. |
| It is the applications responsibility to ensure that the callback function |
| is thread-safe. |
| The parameters to this callback function are:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><em>event</em> is the event object for which the callback function is invoked.</p> |
| </li> |
| <li> |
| <p><em>event_command_exec_status</em> is equal to the <em>command_exec_callback_type</em> |
| used while registering the callback. |
| Refer to the <a href="#kernel-argument-info-table">Kernel Argument Queries</a> |
| table for the command execution status values. |
| If the callback is called as the result of the command associated with |
| event being abnormally terminated, an appropriate error code for the |
| error that caused the termination will be passed to |
| <em>event_command_exec_status</em> instead.</p> |
| </li> |
| <li> |
| <p><em>user_data</em> is a pointer to user supplied data.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p><em>user_data</em> will be passed as the <em>user_data</em> argument when <em>pfn_notify</em> is |
| called. |
| <em>user_data</em> can be <code>NULL</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>All callbacks registered for an event object must be called. |
| All enqueued callbacks shall be called before the event object is destroyed. |
| Callbacks must return promptly. |
| The behavior of calling expensive system routines, OpenCL API calls to |
| create contexts or command-queues, or blocking OpenCL operations from the |
| following list below, in a callback is undefined.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>clFinish</strong>,</p> |
| </li> |
| <li> |
| <p><strong>clWaitForEvents</strong>,</p> |
| </li> |
| <li> |
| <p>blocking calls to <strong>clEnqueueReadBuffer</strong>, <strong>clEnqueueReadBufferRect</strong>,</p> |
| </li> |
| <li> |
| <p><strong>clEnqueueWriteBuffer</strong>, <strong>clEnqueueWriteBufferRect</strong>,</p> |
| </li> |
| <li> |
| <p>blocking calls to <strong>clEnqueueReadImage</strong> and <strong>clEnqueueWriteImage</strong>,</p> |
| </li> |
| <li> |
| <p>blocking calls to <strong>clEnqueueMapBuffer</strong> and <strong>clEnqueueMapImage</strong>,</p> |
| </li> |
| <li> |
| <p>blocking calls to <strong>clBuildProgram</strong>, <strong>clCompileProgram</strong> or |
| <strong>clLinkProgram</strong>,</p> |
| </li> |
| <li> |
| <p>blocking calls to <strong>clEnqueueSVMMemcpy</strong> or <strong>clEnqueueSVMMap</strong></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>If an application needs to wait for completion of a routine from the above |
| list in a callback, please use the non-blocking form of the function, and |
| assign a completion callback to it to do the remainder of your work. |
| Note that when a callback (or other code) enqueues commands to a |
| command-queue, the commands are not required to begin execution until the |
| queue is flushed. |
| In standard usage, blocking enqueue calls serve this role by implicitly |
| flushing the queue. |
| Since blocking calls are not permitted in callbacks, those callbacks that |
| enqueue commands on a command queue should either call <strong>clFlush</strong> on the |
| queue before returning or arrange for <strong>clFlush</strong> to be called later on |
| another thread.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clSetEventCallback</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_EVENT if <em>event</em> is not a valid event object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>pfn_event_notify</em> is <code>NULL</code> or if |
| <em>command_exec_callback_type</em> is not CL_SUBMITTED, CL_RUNNING or</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clRetainEvent(cl_event event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>increments the <em>event</em> reference count. |
| The OpenCL commands that return an event perform an implicit retain.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clRetainEvent</strong> returns CL_SUCCESS if the function is executed successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_EVENT if <em>event</em> is not a valid event object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>To release an event, use the following function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clReleaseEvent(cl_event event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>decrements the <em>event</em> reference count.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clReleaseEvent</strong> returns CL_SUCCESS if the function is executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_EVENT if <em>event</em> is not a valid event object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The event object is deleted once the reference count becomes zero, the |
| specific command identified by this event has completed (or terminated) and |
| there are no commands in the command-queues of a context that require a wait |
| for this event to complete. |
| Using this function to release a reference that was not obtained by creating |
| the object or by calling <strong>clRetainEvent</strong> causes undefined behavior.</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="paragraph"> |
| <p>Developers should be careful when releasing their last reference count on |
| events created by <strong>clCreateUserEvent</strong> that have not yet been set to status |
| of CL_COMPLETE or an error. |
| If the user event was used in the event_wait_list argument passed to a |
| <strong>clEnqueue*</strong> API or another application host thread is waiting for it in |
| <strong>clWaitForEvents</strong>, those commands and host threads will continue to wait for |
| the event status to reach CL_COMPLETE or error, even after the application |
| has released the object. |
| Since in this scenario the application has released its last reference count |
| to the user event, it would be in principle no longer valid for the |
| application to change the status of the event to unblock all the other |
| machinery. |
| As a result the waiting tasks will wait forever, and associated events, |
| cl_mem objects, command queues and contexts are likely to leak. |
| In-order command queues caught up in this deadlock may cease to do any work.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="markers-barriers-waiting-for-events">5.12. Markers, Barriers and Waiting for Events</h3> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueMarkerWithWaitList(cl_command_queue command_queue, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a marker command which waits for either a list of events to |
| complete, or if the list is empty it waits for all commands previously |
| enqueued in <em>command_queue</em> to complete before it completes. |
| This command returns an <em>event</em> which can be waited on, i.e. this event can |
| be waited on to insure that all events either in the <em>event_wait_list</em> or |
| all previously enqueued commands, queued before this command to |
| <em>command_queue</em>, have completed.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> is a valid host command-queue.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>event_wait_list</em> is <code>NULL</code>, then this particular command waits until all |
| previous enqueued commands to <em>command_queue</em> have completed.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular command. |
| Event objects are unique and can be used to identify this marker command |
| later on. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueMarkerWithWaitList</strong> returns CL_SUCCESS if the function is |
| successfully executed. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and events |
| in <em>event_wait_list</em> are not the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueBarrierWithWaitList(cl_command_queue command_queue, |
| cl_uint num_events_in_wait_list, |
| <span class="directive">const</span> cl_event *event_wait_list, |
| cl_event *event)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>enqueues a barrier command which waits for either a list of events to |
| complete, or if the list is empty it waits for all commands previously |
| enqueued in <em>command_queue</em> to complete before it completes. |
| This command blocks command execution, that is, any following commands |
| enqueued after it do not execute until it completes. |
| This command returns an <em>event</em> which can be waited on, i.e. this event can |
| be waited on to insure that all events either in the <em>event_wait_list</em> or |
| all previously enqueued commands, queued before this command to |
| <em>command_queue</em>, have completed</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>command_queue</em> is a valid host command-queue.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to |
| complete before this particular command can be executed.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0. |
| If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by |
| <em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be |
| greater than 0. |
| The events specified in <em>event_wait_list</em> act as synchronization points. |
| The context associated with events in <em>event_wait_list</em> and <em>command_queue</em> |
| must be the same. |
| The memory associated with <em>event_wait_list</em> can be reused or freed after |
| the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>event_wait_list</em> is <code>NULL</code>, then this particular command waits until all |
| previous enqueued commands to <em>command_queue</em> have completed.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> returns an event object that identifies this particular command. |
| Event objects are unique and can be used to identify this barrier command |
| later on. |
| <em>event</em> can be <code>NULL</code> in which case it will not be possible for the |
| application to query the status of this command or queue a wait for this |
| command to complete. |
| If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the |
| <em>event</em> argument should not refer to an element of the <em>event_wait_list</em> |
| array.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clEnqueueBarrierWithWaitList</strong> returns CL_SUCCESS if the function is |
| successfully executed. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and events |
| in <em>event_wait_list</em> are not the same.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and |
| <em>num_events_in_wait_list</em> > 0, or <em>event_wait_list</em> is not <code>NULL</code> and |
| <em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em> |
| are not valid events.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_out_of_order_execution_of_kernels_and_memory_object_commands">5.13. Out-of-order Execution of Kernels and Memory Object Commands</h3> |
| <div class="paragraph"> |
| <p>The OpenCL functions that are submitted to a command-queue are enqueued in |
| the order the calls are made but can be configured to execute in-order or |
| out-of-order. |
| The <em>properties</em> argument in <strong>clCreateCommandQueueWithProperties</strong> can be |
| used to specify the execution order.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE property of a command-queue is |
| not set, the commands enqueued to a command-queue execute in order. |
| For example, if an application calls <strong>clEnqueueNDRangeKernel</strong> to execute |
| kernel A followed by a <strong>clEnqueueNDRangeKernel</strong> to execute kernel B, the |
| application can assume that kernel A finishes first and then kernel B is |
| executed. |
| If the memory objects output by kernel A are inputs to kernel B then kernel |
| B will see the correct data in memory objects produced by execution of |
| kernel A. |
| If the CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE property of a command-queue is |
| set, then there is no guarantee that kernel A will finish before kernel B |
| starts execution.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Applications can configure the commands enqueued to a command-queue to |
| execute out-of-order by setting the CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE |
| property of the command-queue. |
| This can be specified when the command-queue is created. |
| In out-of-order execution mode there is no guarantee that the enqueued |
| commands will finish execution in the order they were queued. |
| As there is no guarantee that kernels will be executed in order, i.e. based |
| on when the <strong>clEnqueueNDRangeKernel</strong> calls are made within a command-queue, |
| it is therefore possible that an earlier <strong>clEnqueueNDRangeKernel</strong> call to |
| execute kernel A identified by event A may execute and/or finish later than |
| a <strong>clEnqueueNDRangeKernel</strong> call to execute kernel B which was called by the |
| application at a later point in time. |
| To guarantee a specific order of execution of kernels, a wait on a |
| particular event (in this case event A) can be used. |
| The wait for event A can be specified in the <em>event_wait_list</em> argument to |
| <strong>clEnqueueNDRangeKernel</strong> for kernel B.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In addition, a marker (<strong>clEnqueueMarkerWithWaitList</strong>) or a barrier |
| (<strong>clEnqueueBarrierWithWaitList</strong>) command can be enqueued to the |
| command-queue. |
| The marker command ensures that previously enqueued commands identified by |
| the list of events to wait for (or all previous commands) have finished. |
| A barrier command is similar to a marker command, but additionally |
| guarantees that no later-enqueued commands will execute until the waited-for |
| commands have executed.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Similarly, commands to read, write, copy or map memory objects that are |
| enqueued after <strong>clEnqueueNDRangeKernel</strong> or <strong>clEnqueueNativeKernel</strong> commands |
| are not guaranteed to wait for kernels scheduled for execution to have |
| completed (if the CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE property is set). |
| To ensure correct ordering of commands, the event object returned by |
| <strong>clEnqueueNDRangeKernel</strong> or <strong>clEnqueueNativeKernel</strong> can be used to enqueue a |
| wait for event or a barrier command can be enqueued that must complete |
| before reads or writes to the memory object(s) occur.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="profiling-operations">5.14. Profiling Operations on Memory Objects and Kernels</h3> |
| <div class="paragraph"> |
| <p>This section describes the profiling of OpenCL functions that are enqueued |
| as commands to a command-queue. Profiling of OpenCL commands can be enabled |
| by using a command-queue created with CL_QUEUE_PROFILING_ENABLE |
| flag set in <em>properties</em> argument to <strong>clCreateCommandQueueWithProperties</strong>. |
| When profiling is enabled, the event objects that are created from |
| enqueuing a command store a timestamp for each of their state transitions.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If profiling is enabled, the function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clGetEventProfilingInfo(cl_event event, |
| cl_profiling_info param_name, |
| size_t param_value_size, |
| <span class="directive">void</span> *param_value, |
| size_t *param_value_size_ret)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>returns profiling information for the command associated with event.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>event</em> specifies the event object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_name</em> specifies the profiling data to query. |
| The list of supported <em>param_name</em> types and the information returned in |
| <em>param_value</em> by <strong>clGetEventProfilingInfo</strong> is described in the |
| <a href="#event-profiling-info-table">Event Profiling Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value</em> is a pointer to memory where the appropriate result being |
| queried is returned. |
| If <em>param_value</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to |
| by <em>param_value</em>. |
| This size must be ≥ size of return type as described in the |
| <a href="#event-profiling-info-table">Event Profiling Queries</a> table.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>param_value_size_ret</em> returns the actual size in bytes of data being |
| queried by <em>param_name</em>. |
| If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p> |
| </div> |
| <table id="event-profiling-info-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 34. <strong>clGetEventProfilingInfo</strong> parameter queries</caption> |
| <colgroup> |
| <col style="width: 34%;"> |
| <col style="width: 33%;"> |
| <col style="width: 33%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_profiling_info</strong></th> |
| <th class="tableblock halign-left valign-top">Return Type</th> |
| <th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROFILING_COMMAND_QUEUED</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">A 64-bit value that describes the current device time counter in |
| nanoseconds when the command identified by event is enqueued in a |
| command-queue by the host.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROFILING_COMMAND_SUBMIT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">A 64-bit value that describes the current device time counter in |
| nanoseconds when the command identified by event that has been |
| enqueued is submitted by the host to the device associated with the |
| command-queue.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROFILING_COMMAND_START</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">A 64-bit value that describes the current device time counter in |
| nanoseconds when the command identified by event starts execution on |
| the device.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROFILING_COMMAND_END</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">A 64-bit value that describes the current device time counter in |
| nanoseconds when the command identified by event has finished |
| execution on the device.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROFILING_COMMAND_COMPLETE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">A 64-bit value that describes the current device time counter in |
| nanoseconds when the command identified by event and any child |
| commands enqueued by this command on the device have finished |
| execution.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>The unsigned 64-bit values returned can be used to measure the time in |
| nano-seconds consumed by OpenCL commands.</p> |
| </div> |
| <div class="paragraph"> |
| <p>OpenCL devices are required to correctly track time across changes in device |
| frequency and power states. |
| The CL_DEVICE_PROFILING_TIMER_RESOLUTION specifies the resolution of the |
| timer i.e. the number of nanoseconds elapsed before the timer is |
| incremented.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clGetEventProfilingInfo</strong> returns CL_SUCCESS if the function is executed |
| successfully and the profiling information has been recorded. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_PROFILING_INFO_NOT_AVAILABLE if the CL_QUEUE_PROFILING_ENABLE flag is |
| not set for the command-queue, if the execution status of the command |
| identified by <em>event</em> is not CL_COMPLETE or if <em>event</em> is a user event |
| object.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes |
| specified by <em>param_value_size</em> is < size of return type as described in |
| the <a href="#event-profiling-info-table">Event Profiling Queries</a> table and |
| <em>param_value</em> is not <code>NULL</code>.</p> |
| </li> |
| <li> |
| <p>CL_INVALID_EVENT if <em>event</em> is a not a valid event object.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_flush_and_finish">5.15. Flush and Finish</h3> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clFlush(cl_command_queue command_queue)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>issues all previously queued OpenCL commands in <em>command_queue_to the device |
| associated with_command_queue</em>. |
| <strong>clFlush</strong> only guarantees that all queued commands to <em>command_queue</em> will |
| eventually be submitted to the appropriate device. |
| There is no guarantee that they will be complete after <strong>clFlush</strong> returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clFlush</strong> returns CL_SUCCESS if the function call was executed successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Any blocking commands queued in a command-queue and <strong>clReleaseCommandQueue</strong> |
| perform an implicit flush of the command-queue. |
| These blocking commands are <strong>clEnqueueReadBuffer</strong>, |
| <strong>clEnqueueReadBufferRect</strong>, <strong>clEnqueueReadImage</strong>, with <em>blocking_read</em> set to |
| CL_TRUE; <strong>clEnqueueWriteBuffer</strong>, <strong>clEnqueueWriteBufferRect</strong>, |
| <strong>clEnqueueWriteImage</strong> with <em>blocking_write</em> set to CL_TRUE; |
| <strong>clEnqueueMapBuffer</strong>, <strong>clEnqueueMapImage</strong> with <em>blocking_map</em> set to |
| CL_TRUE; <strong>clEnqueueSVMMemcpy</strong> with <em>blocking_copy</em> set to CL_TRUE; |
| <strong>clEnqueueSVMMap</strong> with <em>blocking_map</em> set to CL_TRUE or <strong>clWaitForEvents</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To use event objects that refer to commands enqueued in a command-queue as |
| event objects to wait on by commands enqueued in a different command-queue, |
| the application must call a <strong>clFlush</strong> or any blocking commands that perform |
| an implicit flush of the command-queue where the commands that refer to |
| these event objects are enqueued.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_int clFinish(cl_command_queue command_queue)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>blocks until all previously queued OpenCL commands in <em>command_queue</em> are |
| issued to the associated device and have completed. |
| <strong>clFinish</strong> does not return until all previously queued commands in |
| <em>command_queue</em> have been processed and completed. |
| <strong>clFinish</strong> is also a synchronization point.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>clFinish</strong> returns CL_SUCCESS if the function call was executed |
| successfully. |
| Otherwise, it returns one of the following errors:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host |
| command-queue.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required |
| by the OpenCL implementation on the device.</p> |
| </li> |
| <li> |
| <p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources |
| required by the OpenCL implementation on the host.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_associated_opencl_specification">6. Associated OpenCL specification</h2> |
| <div class="sectionbody"> |
| <div class="sect2"> |
| <h3 id="spirv-il">6.1. SPIR-V Intermediate language</h3> |
| <div class="paragraph"> |
| <p>The OpenCL 2.2 specification requires support for the SPIR-V intermediate |
| language that allows offline, or linked online, compilation to a binary |
| format that may be consumed by the <strong>clCreateProgramWithIL</strong> interface.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The OpenCL specification includes a specification for the SPIR-V 1.2 |
| intermediate language as a cross-platform input language. |
| In addition, platform vendors may support their own IL if this is |
| appropriate. |
| The OpenCL runtime will return a list of supported IL versions using the |
| <strong>CL_DEVICE_IL_VERSION</strong> parameter to the <strong>clGetDeviceInfo</strong> query.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="opencl-extensions">6.2. Extensions to OpenCL</h3> |
| <div class="paragraph"> |
| <p>In addition to the specification of core features, OpenCL provides a number |
| of extensions to the API, kernel language or intermediate representation. |
| These features are defined in the OpenCL 2.2 extensions specification |
| document.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Extensions defined against earlier versions of the OpenCL specifications, |
| whether the API or language specification, are defined in the matching |
| versions of the extension specification document.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_support_for_earlier_opencl_c_kernel_languages">6.3. Support for earlier OpenCL C kernel languages</h3> |
| <div class="paragraph"> |
| <p>The OpenCL C kernel language is not defined in the OpenCL 2.2 specification. |
| New language features are described in the OpenCL C++ specification as well |
| as the SPIR-V 1.2 specification and in kernel languages that target it. |
| A kernel language defined by any of the OpenCL 1.0, OpenCL 1.1, OpenCL 1.2 |
| and OpenCL 2.0 kernel language specifications as well as kernels language |
| extensions defined by the matching versions of OpenCL extension |
| specifications are valid to pass to <strong>clCreateProgramWithSource</strong> executing |
| against an OpenCL 2.2 runtime.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="opencl-embedded-profile">7. OpenCL Embedded Profile</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>The OpenCL 2.2 specification describes the feature requirements for desktop |
| platforms. |
| This section describes the OpenCL 2.2 embedded profile that allows us to |
| target a subset of the OpenCL 2.2 specification for handheld and embedded |
| platforms. |
| The optional extensions defined in the OpenCL 2.2 Extension Specification |
| apply to both profiles.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The OpenCL 2.2 embedded profile has the following restrictions:</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p>64 bit integers i.e. long, ulong including the appropriate vector data |
| types and operations on 64-bit integers are optional. |
| The <strong>cles_khr_int64</strong><sup>1</sup> extension string will be reported if the |
| embedded profile implementation supports 64-bit integers.</p> |
| <div class="openblock"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">1</dt> |
| <dd> |
| <p>Note that the performance of 64-bit integer arithmetic can vary |
| significantly between embedded devices.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| </li> |
| <li> |
| <p><span class="line-through">Support for 3D images is optional.</span></p> |
| <div class="openblock line-through"> |
| <div class="content"> |
| <div class="paragraph"> |
| <p>If <strong>CL_DEVICE_IMAGE3D_MAX_WIDTH</strong>, <strong>CL_DEVICE_IMAGE3D_MAX_HEIGHT</strong> and |
| <strong>CL_DEVICE_IMAGE3D_MAX_DEPTH</strong> are zero, the call to <strong>clCreateImage</strong> in the |
| embedded profile will fail to create the 3D image. |
| The <em>errcode_ret</em> argument in <strong>clCreateImage</strong> returns CL_INVALID_OPERATION. |
| Declaring arguments of type <code>image3d_t</code> in a kernel will result in a |
| compilation error.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <strong>CL_DEVICE_IMAGE3D_MAX_WIDTH</strong>, <strong>CL_DEVICE_IMAGE3D_MAX_HEIGHT</strong> and |
| CL_DEVICE_IMAGE3D_MAX_DEPTH > 0, 3D images are supported by the OpenCL |
| embedded profile implementation. |
| <strong>clCreateImage</strong> will work as defined by the OpenCL specification. |
| The <code>image3d_t</code> data type can be used in a kernel(s).</p> |
| </div> |
| </div> |
| </div> |
| </li> |
| <li> |
| <p><span class="line-through">Support for 2D image array writes is optional. |
| If the <strong>cles_khr_2d_image_array_writes</strong> extension is supported by the |
| embedded profile, writes to 2D image arrays are supported.</span></p> |
| </li> |
| <li> |
| <p><span class="line-through">Image and image arrays created with an |
| <code>image_channel_data_type</code> value of CL_FLOAT or CL_HALF_FLOAT can only be |
| used with samplers that use a filter mode of CL_FILTER_NEAREST. |
| The values returned by <strong>read_imagef</strong> and <strong>read_imageh</strong><sup>2</sup> for 2D and 3D |
| images if <code>image_channel_data_type</code> value is CL_FLOAT or CL_HALF_FLOAT |
| and sampler with filter_mode = CL_FILTER_LINEAR are undefined.</span></p> |
| <div class="openblock"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">2</dt> |
| <dd> |
| <p>If <strong>cl_khr_fp16</strong> extension is supported.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| </li> |
| <li> |
| <p>The mandated minimum single precision floating-point capability given by |
| CL_DEVICE_SINGLE_FP_CONFIG is CL_FP_ROUND_TO_ZERO or |
| CL_FP_ROUND_TO_NEAREST. |
| If CL_FP_ROUND_TO_NEAREST is supported, the default rounding mode will |
| be round to nearest even; otherwise the default rounding mode will be |
| round to zero.</p> |
| </li> |
| <li> |
| <p>The single precision floating-point operations (addition, subtraction |
| and multiplication) shall be correctly rounded. |
| Zero results may always be positive 0.0. |
| The accuracy of division and sqrt are given in the SPIR-V OpenCL |
| environment specification.</p> |
| <div class="openblock"> |
| <div class="content"> |
| <div class="paragraph"> |
| <p>If CL_FP_INF_NAN is not set in CL_DEVICE_SINGLE_FP_CONFIG, and one of the |
| operands or the result of addition, subtraction, multiplication or division |
| would signal the overflow or invalid exception (see IEEE 754 specification), |
| the value of the result is implementation-defined. |
| Likewise, single precision comparison operators (<, >, <=, >=, ==, |
| !=) return implementation-defined values when one or more operands is a |
| NaN.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In all cases, conversions (see the SPIR-V OpenCL environment specification) |
| shall be correctly rounded as described for the FULL_PROFILE, including |
| those that consume or produce an INF or NaN. |
| The built-in math functions shall behave as described for the FULL_PROFILE, |
| including edge case behavior but with slightly different accuracy rules. |
| Edge case behavior and accuracy rules are described in the SPIR-V OpenCL |
| environment specification.</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>If addition, subtraction and multiplication have default round to zero |
| rounding mode, then <strong>fract</strong>, <strong>fma</strong> and <strong>fdim</strong> shall produce the correctly |
| rounded result for round to zero rounding mode.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This relaxation of the requirement to adhere to IEEE 754 requirements for |
| basic floating-point operations, though extremely undesirable, is to provide |
| flexibility for embedded devices that have lot stricter requirements on |
| hardware area budgets.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| </div> |
| </div> |
| </li> |
| <li> |
| <p>Denormalized numbers for the half data type which may be generated when |
| converting a float to a half using variants of the <strong>vstore_half</strong> |
| function or when converting from a half to a float using variants of the |
| <strong>vload_half</strong> function can be flushed to zero. |
| The SPIR-V environment specification for details.</p> |
| </li> |
| <li> |
| <p>The precision of conversions from CL_UNORM_INT8, CL_SNORM_INT8, |
| CL_UNORM_INT16, CL_SNORM_INT16, CL_UNORM_INT_101010 and |
| CL_UNORM_INT_101010_2 to float is ≤ 2 ulp for the embedded profile |
| instead of ≤ 1.5 ulp as defined in the full profile. |
| The exception cases described in the full profile and given below apply |
| to the embedded profile.</p> |
| <div class="openblock"> |
| <div class="content"> |
| <div class="paragraph"> |
| <p>For CL_UNORM_INT8</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>0 must convert to 0.0f and</p> |
| </li> |
| <li> |
| <p>255 must convert to 1.0f</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>For CL_UNORM_INT16</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>0 must convert to 0.0f and</p> |
| </li> |
| <li> |
| <p>65535 must convert to 1.0f</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>For CL_SNORM_INT8</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>-128 and -127 must convert to -1.0f,</p> |
| </li> |
| <li> |
| <p>0 must convert to 0.0f and</p> |
| </li> |
| <li> |
| <p>127 must convert to 1.0f</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>For CL_SNORM_INT16</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>-32768 and -32767 must convert to -1.0f,</p> |
| </li> |
| <li> |
| <p>0 must convert to 0.0f and</p> |
| </li> |
| <li> |
| <p>32767 must convert to 1.0f</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>For CL_UNORM_INT_101010</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>0 must convert to 0.0f and</p> |
| </li> |
| <li> |
| <p>1023 must convert to 1.0f</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>For CL_UNORM_INT_101010_2</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>0 must convert to 0.0f and</p> |
| </li> |
| <li> |
| <p>1023 must convert to 1.0f (for RGB)</p> |
| </li> |
| <li> |
| <p>3 must convert to 1.0f (for A)</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </li> |
| </ol> |
| </div> |
| <div class="paragraph"> |
| <p>The following optional extensions defined in the OpenCL 2.2 Extension |
| Specification are available to the embedded profile:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>cl_khr_int64_base_atomics</strong></p> |
| </li> |
| <li> |
| <p><strong>cl_khr_int64_extended_atomics</strong></p> |
| </li> |
| <li> |
| <p><strong>cl_khr_fp16</strong></p> |
| </li> |
| <li> |
| <p><strong>cles_khr_int64</strong>. |
| If double precision is supported i.e. CL_DEVICE_DOUBLE_FP_CONFIG is not |
| zero, then cles_khr_int64 must also be supported.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>CL_PLATFORM_PROFILE defined in the <a href="#platform-queries-table">OpenCL Platform |
| Queries</a> table will return the string EMBEDDED_PROFILE if the OpenCL |
| implementation supports the embedded profile only.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The minimum maximum values specified in the <a href="#device-queries-table">OpenCL |
| Device Queries</a> table that have been modified for the OpenCL embedded |
| profile are listed in the <a href="#embedded-device-queries-table">OpenCL Embedded |
| Device Queries</a> table.</p> |
| </div> |
| <table id="embedded-device-queries-table" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 35. OpenCL Embedded Device Queries</caption> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top"><strong>cl_device_info</strong></th> |
| <th class="tableblock halign-left valign-top">Return Type</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_MAX_READ_IMAGE_ARGS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max number of image objects arguments of a kernel declared with the |
| <code>read_only</code> qualifier. |
| The minimum value is 8 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_MAX_WRITE_IMAGE_ARGS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max number of image objects arguments of a kernel declared with the |
| <code>write_only</code> qualifier. |
| The minimum value is 8 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max number of image objects arguments of a kernel declared with the |
| <code>write_only</code> or <code>read_write</code> qualifier. |
| The minimum value is 8 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_IMAGE2D_MAX_WIDTH</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max width of 2D image in pixels. |
| The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_IMAGE2D_MAX_HEIGHT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max height of 2D image in pixels. |
| The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_IMAGE3D_MAX_WIDTH</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max width of 3D image in pixels. |
| The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_IMAGE3D_MAX_HEIGHT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max height of 3D image in pixels. |
| The minimum value is 2048.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_IMAGE3D_MAX_DEPTH</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max depth of 3D image in pixels. |
| The minimum value is 2048.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_IMAGE_MAX_BUFFER_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max number of pixels for a 1D image created from a buffer object.</p> |
| <p class="tableblock"> The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_IMAGE_MAX_ARRAY_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max number of images in a 1D or 2D image array.</p> |
| <p class="tableblock"> The minimum value is 256 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_MAX_SAMPLERS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum number of samplers that can be used in a kernel.</p> |
| <p class="tableblock"> The minimum value is 8 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_MAX_PARAMETER_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max size in bytes of all arguments that can be passed to a kernel. |
| The minimum value is 256 bytes for devices that are not of type |
| CL_DEVICE_TYPE_CUSTOM.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_SINGLE_FP_CONFIG</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_fp_config</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Describes single precision floating-point capability of the device. |
| This is a bit-field that describes one or more of the following |
| values:</p> |
| <p class="tableblock"> CL_FP_DENORM - denorms are supported</p> |
| <p class="tableblock"> CL_FP_INF_NAN - INF and quiet NaNs are supported.</p> |
| <p class="tableblock"> CL_FP_ROUND_TO_NEAREST - round to nearest even rounding mode |
| supported</p> |
| <p class="tableblock"> CL_FP_ROUND_TO_ZERO - round to zero rounding mode supported</p> |
| <p class="tableblock"> CL_FP_ROUND_TO_INF - round to positive and negative infinity |
| rounding modes supported</p> |
| <p class="tableblock"> CL_FP_FMA - IEEE754-2008 fused multiply-add is supported.</p> |
| <p class="tableblock"> CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT - divide and sqrt are correctly |
| rounded as defined by the IEEE754 specification.</p> |
| <p class="tableblock"> CL_FP_SOFT_FLOAT - Basic floating-point operations (such as |
| addition, subtraction, multiplication) are implemented in software.</p> |
| <p class="tableblock"> The mandated minimum floating-point capability is: |
| CL_FP_ROUND_TO_ZERO or CL_FP_ROUND_TO_NEAREST for devices that are |
| not of type CL_DEVICE_TYPE_CUSTOM.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max size in bytes of a constant buffer allocation. |
| The minimum value is 1 KB for devices that are not of type |
| CL_DEVICE_TYPE_CUSTOM.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_MAX_CONSTANT_ARGS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Max number of arguments declared with the <code>__constant</code> qualifier |
| in a kernel. |
| The minimum value is 4 for devices that are not of type |
| CL_DEVICE_TYPE_CUSTOM.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_LOCAL_MEM_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Size of local memory arena in bytes. |
| The minimum value is 1 KB for devices that are not of type |
| CL_DEVICE_TYPE_CUSTOM.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_COMPILER_AVAILABLE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_FALSE if the implementation does not have a compiler available |
| to compile the program source.</p> |
| <p class="tableblock"> Is CL_TRUE if the compiler is available. |
| This can be CL_FALSE for the embedded platform profile only.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_LINKER_AVAILABLE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_FALSE if the implementation does not have a linker available. |
| Is CL_TRUE if the linker is available.</p> |
| <p class="tableblock"> This can be CL_FALSE for the embedded platform profile only.</p> |
| <p class="tableblock"> This must be CL_TRUE if CL_DEVICE_COMPILER_AVAILABLE is CL_TRUE.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The max. size of the device queue in bytes. |
| The minimum value is 64 KB for the embedded profile</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_PRINTF_BUFFER_SIZE</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum size in bytes of the internal buffer that holds the output |
| of printf calls from a kernel. |
| The minimum value for the EMBEDDED profile is 1 KB.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>If CL_DEVICE_IMAGE_SUPPORT specified in the <a href="#device-queries-table">OpenCL |
| Device Queries</a> table is CL_TRUE, the values assigned to |
| CL_DEVICE_MAX_READ_IMAGE_ARGS, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, |
| CL_DEVICE_IMAGE2D_MAX_WIDTH, CL_DEVICE_IMAGE2D_MAX_HEIGHT, |
| CL_DEVICE_IMAGE3D_MAX_WIDTH, CL_DEVICE_IMAGE3D_MAX_HEIGHT, |
| CL_DEVICE_IMAGE3D_MAX_DEPTH and CL_DEVICE_MAX_SAMPLERS by the implementation |
| must be greater than or equal to the minimum values specified in the |
| <a href="#embedded-device-queries-table">OpenCL Embedded Device Queries</a> table.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_shared_objects_thread_safety">Appendix A: Shared Objects, Thread Safety</h2> |
| <div class="sectionbody"> |
| <div class="sect2"> |
| <h3 id="shared-opencl-objects">Shared OpenCL Objects</h3> |
| <div class="paragraph"> |
| <p>This section describes which objects can be shared across multiple |
| command-queues created within a host process.</p> |
| </div> |
| <div class="paragraph"> |
| <p>OpenCL memory objects, program objects and kernel objects are created using |
| a context and can be shared across multiple command-queues created using the |
| same context. |
| Event objects can be created when a command is queued to a command-queue. |
| These event objects can be shared across multiple command-queues created |
| using the same context.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The application needs to implement appropriate synchronization across |
| threads on the host processor to ensure that the changes to the state of a |
| shared object (such as a command-queue object, memory object, program or |
| kernel object) happen in the correct order (deemed correct by the |
| application) when multiple command-queues in multiple threads are making |
| changes to the state of a shared object.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A command-queue can cache changes to the state of a memory object on the |
| device associated with the command-queue. |
| To synchronize changes to a memory object across command-queues, the |
| application must do the following:</p> |
| </div> |
| <div class="paragraph"> |
| <p>In the command-queue that includes commands that modify the state of a |
| memory object, the application must do the following:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Get appropriate event objects for commands that modify the state of the |
| shared memory object.</p> |
| </li> |
| <li> |
| <p>Call the <strong>clFlush</strong> (or <strong>clFinish</strong>) API to issue any outstanding commands |
| from this command-queue.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>In the command-queue that wants to synchronize to the latest state of a |
| memory object, commands queued by the application must use the appropriate |
| event objects that represent commands that modify the state of the shared |
| memory object as event objects to wait on. |
| This is to ensure that commands that use this shared memory object complete |
| in the previous command-queue before the memory objects are used by commands |
| executing in this command-queue.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The results of modifying a shared resource in one command-queue while it is |
| being used by another command-queue are undefined.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_multiple_host_threads">Multiple Host Threads</h3> |
| <div class="paragraph"> |
| <p>All OpenCL API calls are thread-safe<sup>1</sup> except those that modify the state |
| of cl_kernel objects: <strong>clSetKernelArg</strong>, <strong>clSetKernelArgSVMPointer</strong>, |
| <strong>clSetKernelExecInfo</strong> and <strong>clCloneKernel</strong>. |
| <strong>clSetKernelArg</strong> , <strong>clSetKernelArgSVMPointer</strong>, <strong>clSetKernelExecInfo</strong> and |
| <strong>clCloneKernel</strong> are safe to call from any host thread, and safe to call |
| re-entrantly so long as concurrent calls to any combination of these API |
| calls operate on different cl_kernel objects. |
| The state of the cl_kernel object is undefined if <strong>clSetKernelArg</strong>, |
| <strong>clSetKernelArgSVMPointer</strong>, <strong>clSetKernelExecInfo</strong> or <strong>clCloneKernel</strong> are |
| called from multiple host threads on the same cl_kernel object at the same |
| time<sup>2</sup>. |
| Please note that there are additional limitations as to which OpenCL APIs |
| may be called from <a href="#event-objects">OpenCL callback functions</a>.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">1</dt> |
| <dd> |
| <p>Please refer to the OpenCL glossary for the OpenCL definition of |
| thread-safe. |
| This definition may be different from usage of the term in other |
| contexts.</p> |
| </dd> |
| <dt class="hdlist1">2</dt> |
| <dd> |
| <p>There is an inherent race condition in the design of OpenCL that occurs |
| between setting a kernel argument and using the kernel with |
| <strong>clEnqueueNDRangeKernel</strong>. |
| Another host thread might change the kernel arguments between when a |
| host thread sets the kernel arguments and then enqueues the kernel, |
| causing the wrong kernel arguments to be enqueued. |
| Rather than attempt to share cl_kernel objects among multiple host |
| threads, applications are strongly encouraged to make additional |
| cl_kernel objects for kernel functions for each host thread.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>The behavior of OpenCL APIs called from an interrupt or signal handler is |
| implementation-defined</p> |
| </div> |
| <div class="paragraph"> |
| <p>The OpenCL implementation should be able to create multiple command-queues |
| for a given OpenCL context and multiple OpenCL contexts in an application |
| running on the host processor.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_portability">Appendix B: Portability</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>OpenCL is designed to be portable to other architectures and hardware |
| designs. |
| OpenCL has used at its core a C99 based programming language and follows |
| rules based on that heritage. |
| Floating-point arithmetic is based on the <strong>IEEE-754</strong> and <strong>IEEE-754-2008</strong> |
| standards. |
| The memory objects, pointer qualifiers and weakly ordered memory are |
| designed to provide maximum compatibility with discrete memory architectures |
| implemented by OpenCL devices. |
| Command-queues and barriers allow for synchronization between the host and |
| OpenCL devices. |
| The design, capabilities and limitations of OpenCL are very much a |
| reflection of the capabilities of underlying hardware.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Unfortunately, there are a number of areas where idiosyncrasies of one |
| hardware platform may allow it to do some things that do not work on |
| another. |
| By virtue of the rich operating system resident on the CPU, on some |
| implementations the kernels executing on a CPU may be able to call out to |
| system services whereas the same calls on the GPU will likely fail for now. |
| Since there is some advantage to having these services available for |
| debugging purposes, implementations can use the OpenCL extension mechanism |
| to implement these services.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Likewise, the heterogeneity of computing architectures might mean that a |
| particular loop construct might execute at an acceptable speed on the CPU |
| but very poorly on a GPU, for example. |
| CPUs are designed in general to work well on latency sensitive algorithms on |
| single threaded tasks, whereas common GPUs may encounter extremely long |
| latencies, potentially orders of magnitude worse. |
| A developer interested in writing portable code may find that it is |
| necessary to test his design on a diversity of hardware designs to make sure |
| that key algorithms are structured in a way that works well on a diversity |
| of hardware. |
| We suggest favoring more work-items over fewer. |
| It is anticipated that over the coming months and years experience will |
| produce a set of best practices that will help foster a uniformly favorable |
| experience on a diversity of computing devices.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Of somewhat more concern is the topic of endianness. |
| Since a majority of devices supported by the initial implementation of |
| OpenCL are little-endian, developers need to make sure that their kernels |
| are tested on both big-endian and little-endian devices to ensure source |
| compatibility with OpenCL devices now and in the future. |
| The endian attribute qualifier is supported by the SPIR-V IL to allow |
| developers to specify whether the data uses the endianness of the host or |
| the OpenCL device. |
| This allows the OpenCL compiler to do appropriate endian-conversion on load |
| and store operations from or to this data.</p> |
| </div> |
| <div class="paragraph"> |
| <p>We also describe how endianness can leak into an implementation causing |
| kernels to produce unintended results:</p> |
| </div> |
| <div class="paragraph"> |
| <p>When a big-endian vector machine (e.g. AltiVec, CELL SPE) loads a vector, |
| the order of the data is retained. |
| That is both the order of the bytes within each element and the order of the |
| elements in the vector are the same as in memory. |
| When a little-endian vector machine (e.g. SSE) loads a vector, the order of |
| the data in register (where all the work is done) is reversed. |
| <strong>Both</strong> the order of the bytes within each element and the order of the |
| elements with respect to one another in the vector are reversed.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Memory:</p> |
| </div> |
| <div class="paragraph"> |
| <p>uint4 a =</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> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x00010203</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x04050607</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x08090A0B</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x0C0D0E0F</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>In register (big-endian):</p> |
| </div> |
| <div class="paragraph"> |
| <p>uint4 a =</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> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x00010203</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x04050607</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x08090A0B</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x0C0D0E0F</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>In register (little-endian):</p> |
| </div> |
| <div class="paragraph"> |
| <p>uint4 a =</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> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x0F0E0D0C</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x0B0A0908</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x07060504</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x03020100</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>This allows little-endian machines to use a single vector load to load |
| little-endian data, regardless of how large each piece of data is in the |
| vector. |
| That is the transformation is equally valid whether that vector was a |
| <code>uchar16</code> or a <code>ulong2</code>. |
| Of course, as is well known, little-endian machines actually<sup>1</sup> store their |
| data in reverse byte order to compensate for the little-endian storage |
| format of the array elements:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">1</dt> |
| <dd> |
| <p>Note that we are talking about the programming model here. |
| In reality, little endian systems might choose to simply address their |
| bytes from "the right" or reverse the "order" of the bits in the byte. |
| Either of these choices would mean that no big swap would need to occur |
| in hardware.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>Memory (big-endian):</p> |
| </div> |
| <div class="paragraph"> |
| <p>uint4 a =</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> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x00010203</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x04050607</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x08090A0B</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x0C0D0E0F</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>Memory (little-endian):</p> |
| </div> |
| <div class="paragraph"> |
| <p>uint4 a =</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> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x03020100</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x07060504</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x0B0A0908</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x0F0E0D0C</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>Once that data is loaded into a vector, we end up with this:</p> |
| </div> |
| <div class="paragraph"> |
| <p>In register (big-endian):</p> |
| </div> |
| <div class="paragraph"> |
| <p>uint4 a =</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> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x00010203</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x04050607</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x08090A0B</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x0C0D0E0F</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>In register (little-endian):</p> |
| </div> |
| <div class="paragraph"> |
| <p>uint4 a =</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> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x0C0D0E0F</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x08090A0B</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x04050607</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0x00010203</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>That is, in the process of correcting the endianness of the bytes within |
| each element, the machine ends up reversing the order that the elements |
| appear in the vector with respect to each other within the vector. |
| 0x00010203 appears at the left of the big-endian vector and at the right of |
| the little-endian vector.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When the host and device have different endianness, the developer must |
| ensure that kernel argument values are processed correctly. |
| The implementation may or may not automatically convert endianness of kernel |
| arguments. |
| Developers should consult vendor documentation for guidance on how to handle |
| kernel arguments in these situations.</p> |
| </div> |
| <div class="paragraph"> |
| <p>OpenCL provides a consistent programming model across architectures by |
| numbering elements according to their order in memory. |
| Concepts such as <code>even</code>/<code>odd</code> and <code>high</code>/<code>low</code> follow accordingly. |
| Once the data is loaded into registers, we find that element 0 is at the |
| left of the big-endian vector and element 0 is at the right of the |
| little-endian vector:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">float</span> x[<span class="integer">4</span>]; |
| float4 v = vload4( <span class="integer">0</span>, x );</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Big-endian:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">v contains { x[<span class="integer">0</span>], x[<span class="integer">1</span>], x[<span class="integer">2</span>], x[<span class="integer">3</span>] }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Little-endian:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">v contains { x[<span class="integer">3</span>], x[<span class="integer">2</span>], x[<span class="integer">1</span>], x[<span class="integer">0</span>] }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The compiler is aware that this swap occurs and references elements |
| accordingly. |
| So long as we refer to them by a numeric index such as <code>.s0123456789abcdef</code> |
| or by descriptors such as <code>.xyzw</code>, <code>.hi</code>, <code>.lo</code>, <code>.even</code> and <code>.odd</code>, |
| everything works transparently. |
| Any ordering reversal is undone when the data is stored back to memory. |
| The developer should be able to work with a big-endian programming model and |
| ignore the element ordering problem in the vector …​ for most problems. |
| This mechanism relies on the fact that we can rely on a consistent element |
| numbering. |
| Once we change numbering system, for example by conversion-free casting |
| (using <code>as_type_</code><em>n</em>) a vector to another vector of the same size but a |
| different number of elements, then we get different results on different |
| implementations depending on whether the system is big-endian, or |
| little-endian or indeed has no vector unit at all. |
| (Thus, the behavior of bitcasts to vectors of different numbers of elements |
| is implementation-defined, see section 6.2.4 of OpenCL 2.0 C specification.)</p> |
| </div> |
| <div class="paragraph"> |
| <p>An example follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">float</span> x[<span class="integer">4</span>] = { <span class="float">0</span><span class="float">.0f</span>, <span class="float">1</span><span class="float">.0f</span>, <span class="float">2</span><span class="float">.0f</span>, <span class="float">3</span><span class="float">.0f</span> }; |
| float4 v = vload4( <span class="integer">0</span>, x ); |
| uint4 y = as_uint4(v); <span class="comment">// legal, portable</span> |
| ushort8 z = as_ushort8(v); <span class="comment">// legal, not portable</span> |
| <span class="comment">// element size changed</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Big-endian:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">v contains { <span class="float">0</span><span class="float">.0f</span>, <span class="float">1</span><span class="float">.0f</span>, <span class="float">2</span><span class="float">.0f</span>, <span class="float">3</span><span class="float">.0f</span> } |
| y contains { <span class="hex">0x00000000</span>, <span class="hex">0x3f800000</span>, |
| <span class="hex">0x40000000</span>, <span class="hex">0x40400000</span> } |
| z contains { <span class="hex">0x0000</span>, <span class="hex">0x0000</span>, <span class="hex">0x3f80</span>, <span class="hex">0x0000</span>, |
| <span class="hex">0x4000</span>, <span class="hex">0x0000</span>, <span class="hex">0x4040</span>, <span class="hex">0x0000</span> } |
| z.z is <span class="hex">0x3f80</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Little-endian:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">v contains { <span class="float">3</span><span class="float">.0f</span>, <span class="float">2</span><span class="float">.0f</span>, <span class="float">1</span><span class="float">.0f</span>, <span class="float">0</span><span class="float">.0f</span> } |
| y contains { <span class="hex">0x40400000</span>, <span class="hex">0x40000000</span>, |
| <span class="hex">0x3f800000</span>, <span class="hex">0x00000000</span> } |
| z contains { <span class="hex">0x4040</span>, <span class="hex">0x0000</span>, <span class="hex">0x4000</span>, <span class="hex">0x0000</span>, |
| <span class="hex">0x3f80</span>, <span class="hex">0x0000</span>, <span class="hex">0x0000</span>, <span class="hex">0x0000</span> } |
| z.z is <span class="integer">0</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Here, the value in <code>z.z</code> is not the same between big- and little-endian |
| vector machines</p> |
| </div> |
| <div class="paragraph"> |
| <p>OpenCL could have made it illegal to do a conversion free cast that changes |
| the number of elements in the name of portability. |
| However, while OpenCL provides a common set of operators drawing from the |
| set that are typically found on vector machines, it can not provide access |
| to everything every ISA may offer in a consistent uniform portable manner. |
| Many vector ISAs provide special purpose instructions that greatly |
| accelerate specific operations such as DCT, SAD, or 3D geometry. |
| It is not intended for OpenCL to be so heavy handed that time-critical |
| performance sensitive algorithms can not be written by knowledgeable |
| developers to perform at near peak performance. |
| Developers willing to throw away portability should be able to use the |
| platform-specific instructions in their code. |
| For this reason, OpenCL is designed to allow traditional vector C language |
| programming extensions, such as the AltiVec C Programming Interface or the |
| Intel C programming interfaces (such as those found in emmintrin.h) to be |
| used directly in OpenCL with OpenCL data types as an extension to OpenCL. |
| As these interfaces rely on the ability to do conversion-free casts that |
| change the number of elements in the vector to function properly, OpenCL |
| allows them too.</p> |
| </div> |
| <div class="paragraph"> |
| <p>As a general rule, any operation that operates on vector types in segments |
| that are not the same size as the vector element size may break on other |
| hardware with different endianness or different vector architecture.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Examples might include:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Combining two <code>uchar8</code>'s containing high and low bytes of a ushort, to |
| make a <code>ushort8</code> using <code>.even</code> and <code>.odd</code> operators (please use |
| <strong>upsample()</strong> for this)</p> |
| </li> |
| <li> |
| <p>Any bitcast that changes the number of elements in the vector. |
| (Operations on the new type are non-portable.)</p> |
| </li> |
| <li> |
| <p>Swizzle operations that change the order of data using chunk sizes that |
| are not the same as the element size</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Examples of operations that are portable:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Combining two <code>uint8</code>'s to make a <code>uchar16</code> using <code>.even</code> and <code>.odd</code> |
| operators. |
| For example to interleave left and right audio streams.</p> |
| </li> |
| <li> |
| <p>Any bitcast that does not change the number of elements (e.g. <code>(float4) |
| uint4</code>) — we define the storage format for floating-point types)</p> |
| </li> |
| <li> |
| <p>Swizzle operations that swizzle elements of the same size as the |
| elements of the vector.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>OpenCL has made some additions to C to make application behavior more |
| dependable than C. |
| Most notably in a few cases OpenCL defines the behavior of some operations |
| that are undefined in C99:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>OpenCL provides <code>convert_</code> operators for conversion between all types. |
| C99 does not define what happens when a floating-point type is converted |
| to integer type and the floating-point value lies outside the |
| representable range of the integer type after rounding. |
| When the <code><em>sat</code> variant of the conversion is used, the float shall be |
| converted to the nearest representable integer value. |
| Similarly, OpenCL also makes recommendations about what should happen |
| with NaN. |
| Hardware manufacturers that provide the saturated conversion in hardware |
| may use the saturated conversion hardware for both the saturated and |
| non-saturated versions of the OpenCL <code>convert</em></code> operator. |
| OpenCL does not define what happens for the non-saturated conversions |
| when floating-point operands are outside the range representable |
| integers after rounding.</p> |
| </li> |
| <li> |
| <p>The format of <code>half</code>, <code>float</code>, and <code>double</code> types is defined to be the |
| binary16, binary32 and binary64 formats in the draft IEEE-754 standard. |
| (The latter two are identical to the existing IEEE-754 standard.) You |
| may depend on the positioning and meaning of the bits in these types.</p> |
| </li> |
| <li> |
| <p>OpenCL defines behavior for oversized shift values. |
| Shift operations that shift greater than or equal to the number of bits |
| in the first operand reduce the shift value modulo the number of bits in |
| the element. |
| For example, if we shift an <code>int4</code> left by <code>33</code> bits, OpenCL treats this |
| as shift left by <code>33%32 = 1</code> bit.</p> |
| </li> |
| <li> |
| <p>A number of edge cases for math library functions are more rigorously |
| defined than in C99. |
| Please see <em>section 7.5</em> of the OpenCL 2.0 C specification.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="data-types">Appendix C: Application Data Types</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>This section documents the provided host application types and constant |
| definitions. |
| The documented material describes the commonly defined data structures, |
| types and constant values available to all platforms and architectures. |
| The addition of these details demonstrates our commitment to maintaining a |
| portable programming environment and potentially deters changes to the |
| supplied headers.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="scalar-data-types">Shared Application Scalar Data Types</h3> |
| <div class="paragraph"> |
| <p>The following application scalar types are provided for application |
| convenience.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_char |
| cl_uchar |
| cl_short |
| cl_ushort |
| cl_int |
| cl_uint |
| cl_long |
| cl_ulong |
| cl_half |
| cl_float |
| cl_double</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="vector-data-types">Supported Application Vector Data Types</h3> |
| <div class="paragraph"> |
| <p>Application vector types are unions used to create vectors of the above |
| application scalar types. |
| The following application vector types are provided for application |
| convenience.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_char<n> |
| cl_uchar<n> |
| cl_short<n> |
| cl_ushort<n> |
| cl_int<n> |
| cl_uint<n> |
| cl_long<n> |
| cl_ulong<n> |
| cl_half<n> |
| cl_float<n> |
| cl_double<n></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><em>n</em> can be 2, 3, 4, 8 or 16.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The application scalar and vector data types are defined in the |
| <strong>cl_platform.h</strong> header file.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="alignment-app-data-types">Alignment of Application Data Types</h3> |
| <div class="paragraph"> |
| <p>The user is responsible for ensuring that pointers passed into and out of |
| OpenCL kernels are natively aligned relative to the data type of the |
| parameter as defined in the kernel language and SPIR-V specifications. |
| This implies that OpenCL buffers created with CL_MEM_USE_HOST_PTR need to |
| provide an appropriately aligned host memory pointer that is aligned to the |
| data types used to access these buffers in a kernel(s), that SVM allocations |
| must correctly align and that pointers into SVM allocations must also be |
| correctly aligned. |
| The user is also responsible for ensuring image data passed is aligned to |
| the granularity of the data representing a single pixel (e.g. |
| <code>image_num_channels * sizeof(image_channel_data_type)</code>) except for CL_RGB |
| and CL_RGBx images where the data must be aligned to the granularity of a |
| single channel in a pixel (i.e. <code>sizeof(image_channel_data_type)</code>). |
| This implies that OpenCL images created with CL_MEM_USE_HOST_PTR must align |
| correctly. |
| The image alignment value can be queried using the |
| CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT query. |
| In addition, source pointers for <strong>clEnqueueWriteImage</strong> and other operations |
| that copy to the OpenCL runtime, as well as destination pointers for |
| <strong>clEnqueueReadImage</strong> and other operations that copy from the OpenCL runtime |
| must follow the same alignment rules.</p> |
| </div> |
| <div class="paragraph"> |
| <p>OpenCL makes no requirement about the alignment of OpenCL application |
| defined data types outside of buffers and images, except that the underlying |
| vector primitives (e.g. <code>__cl_float4</code>) where defined shall be directly |
| accessible as such using appropriate named fields in the cl_type union (see |
| <a href="#vector-components">Vector Components</a>. |
| Nevertheless, it is recommended that the <strong>cl_platform.h</strong> header should |
| attempt to naturally align OpenCL defined application data types (e.g. |
| <code>cl_float4</code>) according to their type.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_vector_literals">Vector Literals</h3> |
| <div class="paragraph"> |
| <p>Application vector literals may be used in assignments of individual vector |
| components. |
| Literal usage follows the convention of the underlying application compiler.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">cl_float2 foo = { .s[<span class="integer">1</span>] = <span class="float">2</span><span class="float">.0f</span> }; |
| cl_int8 bar = {{ <span class="integer">2</span>, <span class="integer">4</span>, <span class="integer">6</span>, <span class="integer">8</span>, <span class="integer">10</span>, <span class="integer">12</span>, <span class="integer">14</span>, <span class="integer">16</span> }};</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="vector-components">Vector Components</h3> |
| <div class="paragraph"> |
| <p>The components of application vector types can be addressed using the |
| <code><vector_name>.s[<index>]</code> notation.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">foo.s[<span class="integer">0</span>] = <span class="float">1</span><span class="float">.0f</span>; <span class="comment">// Sets the 1st vector component of foo</span> |
| pos.s[<span class="integer">6</span>] = <span class="integer">2</span>; <span class="comment">// Sets the 7th vector component of bar</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>In some cases vector components may also be accessed using the following |
| notations. |
| These notations are not guaranteed to be supported on all implementations, |
| so their use should be accompanied by a check of the corresponding |
| preprocessor symbol.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="_named_vector_components_notation">Named vector components notation</h4> |
| <div class="paragraph"> |
| <p>Vector data type components may be accessed using the <code>.sN</code>, <code>.sn</code> or |
| <code>.xyzw</code> field naming convention, similar to how they are used within the |
| OpenCL language. |
| Use of the <code>.xyzw</code> field naming convention only allows accessing of the |
| first 4 component fields. |
| Support of these notations is identified by the CL_HAS_NAMED_VECTOR_FIELDS |
| preprocessor symbol. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c"><span class="preprocessor">#ifdef</span> CL_HAS_NAMED_VECTOR_FIELDS |
| cl_float4 foo; |
| cl_int16 bar; |
| foo.x = <span class="float">1</span><span class="float">.0f</span>; <span class="comment">// Set first component</span> |
| foo.s0 = <span class="float">1</span><span class="float">.0f</span>; <span class="comment">// Same as above</span> |
| bar.z = <span class="integer">3</span>; <span class="comment">// Set third component</span> |
| bar.se = <span class="integer">11</span>; <span class="comment">// Same as bar.s[0xe]</span> |
| bar.sD = <span class="integer">12</span>; <span class="comment">// Same as bar.s[0xd]</span> |
| <span class="preprocessor">#endif</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Unlike the OpenCL language type usage of named vector fields, only one |
| component field may be accessed at a time. |
| This restriction prevents the ability to swizzle or replicate components as |
| is possible with the OpenCL language types. |
| Attempting to access beyond the number of components for a type also results |
| in a failure.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c">foo.xy <span class="comment">// illegal - illegal field name combination</span> |
| bar.s1234 <span class="comment">// illegal - illegal field name combination</span> |
| foo.s7 <span class="comment">// illegal - no component s7</span></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_highlow_vector_component_notation">High/Low vector component notation</h4> |
| <div class="paragraph"> |
| <p>Vector data type components may be accessed using the <code>.hi</code> and <code>.lo</code> |
| notation similar to that supported within the language types. |
| Support of this notation is identified by the CL_HAS_HI_LO_VECTOR_FIELDS |
| preprocessor symbol. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c"><span class="preprocessor">#ifdef</span> CL_HAS_HI_LO_VECTOR_FIELDS |
| cl_float4 foo; |
| cl_float2 new_hi = <span class="float">2</span><span class="float">.0f</span>, new_lo = <span class="float">4</span><span class="float">.0f</span>; |
| foo.hi = new_hi; |
| foo.lo = new_lo; |
| <span class="preprocessor">#endif</span></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_native_vector_type_notation">Native vector type notation</h4> |
| <div class="paragraph"> |
| <p>Certain native vector types are defined for providing a mapping of vector |
| types to architecturally builtin vector types. |
| Unlike the above described application vector types, these native types are |
| supported on a limited basis depending on the supporting architecture and |
| compiler.</p> |
| </div> |
| <div class="paragraph"> |
| <p>These types are not unions, but rather convenience mappings to the |
| underlying architectures' builtin vector types. |
| The native types share the name of their application counterparts but are |
| preceded by a double underscore "__".</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example, <code>__cl_float4</code> is the native builtin vector type equivalent of |
| the <code>cl_float4</code> application vector type. |
| The <code>__cl_float4</code> type may provide direct access to the architectural |
| builtin <code>__m128</code> or vector float type, whereas the <code>cl_float4</code> is treated |
| as a union.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In addition, the above described application data types may have native |
| vector data type members for access convenience. |
| The native components are accessed using the <code>.vN</code> sub-vector notation, |
| where <code>N</code> is the number of elements in the sub-vector. |
| In cases where the native type is a subset of a larger type (more |
| components), the notation becomes an index based array of the sub-vector |
| type.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Support of the native vector types is identified by a <code>__CL_TYPEN__</code> |
| preprocessor symbol matching the native type name. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c"><span class="preprocessor">#ifdef</span> __CL_FLOAT4__ <span class="comment">// Check for native cl_float4 type</span> |
| cl_float8 foo; |
| __cl_float4 bar; <span class="comment">// Use of native type</span> |
| bar = foo.v4[<span class="integer">1</span>]; <span class="comment">// Access the second native float4 vector</span> |
| <span class="preprocessor">#endif</span></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_implicit_conversions">Implicit Conversions</h3> |
| <div class="paragraph"> |
| <p>Implicit conversions between application vector types are not supported.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_explicit_casts">Explicit Casts</h3> |
| <div class="paragraph"> |
| <p>Explicit casting of application vector types (<code>cl_typen</code>) is not supported. |
| Explicit casting of native vector types (<code>__cl_typen</code>) is defined by the |
| external compiler.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_other_operators_and_functions">Other operators and functions</h3> |
| <div class="paragraph"> |
| <p>The behavior of standard operators and function on both application vector |
| types (<code>cl_typen</code>) and native vector types (<code>__cl_typen</code>) is defined by |
| the external compiler.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_application_constant_definitions">Application constant definitions</h3> |
| <div class="paragraph"> |
| <p>In addition to the above application type definitions, the following literal |
| definitions are also available.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CHAR_BIT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Bit width of a character</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SCHAR_MAX</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a type <code>cl_char</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SCHAR_MIN</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Minimum value of a type <code>cl_char</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CHAR_MAX</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a type <code>cl_char</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CHAR_MIN</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Minimum value of a type <code>cl_char</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UCHAR_MAX</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a type <code>cl_uchar</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SHORT_MAX</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a type <code>cl_short</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SHORT_MIN</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Minimum value of a type <code>cl_short</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_USHORT_MAX</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a type <code>cl_ushort</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_INT_MAX</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a type <code>cl_int</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_INT_MIN</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Minimum value of a type <code>cl_int</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UINT_MAX</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a type <code>cl_uint</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_LONG_MAX</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a type <code>cl_long</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_LONG_MIN</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Minimum value of a type <code>cl_long</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_ULONG_MAX</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a type <code>cl_ulong</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_DIAG</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Number of decimal digits of precision for the type <code>cl_float</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_MANT_DIG</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Number of digits in the mantissa of type <code>cl_float</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_MAX_10_EXP</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum positive integer such that 10 raised to this power minus one can |
| be represented as a normalized floating-point number of type <code>cl_float</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_MAX_EXP</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum exponent value of type <code>cl_float</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_MIN_10_EXP</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Minimum negative integer such that 10 raised to this power minus one can |
| be represented as a normalized floating-point number of type <code>cl_float</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_MIN_EXP</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Minimum exponent value of type <code>cl_float</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_RADIX</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Base value of type <code>cl_float</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_MAX</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of type <code>cl_float</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_MIN</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Minimum value of type <code>cl_float</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_EPSILON</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Minimum positive floating-point number of type <code>cl_float</code> such that <code>1.0 |
| + CL_FLT_EPSILON != 1</code> is true.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_DIG</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Number of decimal digits of precision for the type <code>cl_double</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_MANT_DIG</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Number of digits in the mantissa of type <code>cl_double</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_MAX_10_EXP</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum positive integer such that 10 raised to this power minus one can |
| be represented as a normalized floating-point number of type <code>cl_double</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_MAX_EXP</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum exponent value of type <code>cl_double</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_MIN_10_EXP</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Minimum negative integer such that 10 raised to this power minus one can |
| be represented as a normalized floating-point number of type <code>cl_double</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_MIN_EXP</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Minimum exponent value of type <code>cl_double</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_RADIX</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Base value of type <code>cl_double</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_MAX</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of type <code>cl_double</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_MIN</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Minimum value of type <code>cl_double</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_EPSILON</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Minimum positive floating-point number of type <code>cl_double</code> such that |
| <code>1.0 + CL_DBL_EPSILON != 1</code> is true.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_NAN</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Macro expanding to a value representing NaN</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_HUGE_VALF</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Largest representative value of type <code>cl_float</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_HUGE_VAL</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Largest representative value of type <code>cl_double</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MAXFLOAT</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of type <code>cl_float</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_INFINITY</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Macro expanding to a value representing infinity</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>These literal definitions are defined in the <strong>cl_platform.h</strong> header.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="check-copy-overlap">Appendix D: CL_MEM_COPY_OVERLAP</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>The following code describes how to determine if there is overlap between |
| the source and destination rectangles specified to <strong>clEnqueueCopyBufferRect</strong> |
| provided the source and destination buffers refer to the same buffer object.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">unsigned</span> <span class="predefined-type">int</span> |
| check_copy_overlap(<span class="directive">const</span> size_t src_origin[], |
| <span class="directive">const</span> size_t dst_origin[], |
| <span class="directive">const</span> size_t region[], |
| <span class="directive">const</span> size_t row_pitch, |
| <span class="directive">const</span> size_t slice_pitch ) |
| { |
| <span class="directive">const</span> size_t slice_size = (region[<span class="integer">1</span>] - <span class="integer">1</span>) * row_pitch + region[<span class="integer">0</span>]; |
| <span class="directive">const</span> size_t block_size = (region[<span class="integer">2</span>] - <span class="integer">1</span>) * slice_pitch + slice_size; |
| <span class="directive">const</span> size_t src_start = src_origin[<span class="integer">2</span>] * slice_pitch |
| + src_origin[<span class="integer">1</span>] * row_pitch |
| + src_origin[<span class="integer">0</span>]; |
| <span class="directive">const</span> size_t src_end = src_start + block_size; |
| <span class="directive">const</span> size_t dst_start = dst_origin[<span class="integer">2</span>] * slice_pitch |
| + dst_origin[<span class="integer">1</span>] * row_pitch |
| + dst_origin[<span class="integer">0</span>]; |
| <span class="directive">const</span> size_t dst_end = dst_start + block_size; |
| |
| <span class="comment">/* No overlap if dst ends before src starts or if src ends |
| * before dst starts. |
| */</span> |
| <span class="keyword">if</span>( (dst_end <= src_start) || (src_end <= dst_start) ){ |
| <span class="keyword">return</span> <span class="integer">0</span>; |
| } |
| |
| <span class="comment">/* No overlap if region[0] for dst or src fits in the gap |
| * between region[0] and row_pitch. |
| */</span> |
| { |
| <span class="directive">const</span> size_t src_dx = src_origin[<span class="integer">0</span>] % row_pitch; |
| <span class="directive">const</span> size_t dst_dx = dst_origin[<span class="integer">0</span>] % row_pitch; |
| |
| <span class="keyword">if</span>( ((dst_dx >= src_dx + region[<span class="integer">0</span>]) && |
| (dst_dx + region[<span class="integer">0</span>] <= src_dx + row_pitch)) || |
| ((src_dx >= dst_dx + region[<span class="integer">0</span>]) && |
| (src_dx + region[<span class="integer">0</span>] <= dst_dx + row_pitch)) ) |
| { |
| <span class="keyword">return</span> <span class="integer">0</span>; |
| } |
| } |
| |
| <span class="comment">/* No overlap if region[1] for dst or src fits in the gap |
| * between region[1] and slice_pitch. |
| */</span> |
| { |
| <span class="directive">const</span> size_t src_dy = |
| (src_origin[<span class="integer">1</span>] * row_pitch + src_origin[<span class="integer">0</span>]) % slice_pitch; |
| <span class="directive">const</span> size_t dst_dy = |
| (dst_origin[<span class="integer">1</span>] * row_pitch + dst_origin[<span class="integer">0</span>]) % slice_pitch; |
| |
| <span class="keyword">if</span>( ((dst_dy >= src_dy + slice_size) && |
| (dst_dy + slice_size <= src_dy + slice_pitch)) || |
| ((src_dy >= dst_dy + slice_size) && |
| (src_dy + slice_size <= dst_dy + slice_pitch)) ) { |
| <span class="keyword">return</span> <span class="integer">0</span>; |
| } |
| } |
| |
| <span class="comment">/* Otherwise src and dst overlap. */</span> |
| <span class="keyword">return</span> <span class="integer">1</span>; |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_changes">Appendix E: Changes</h2> |
| <div class="sectionbody"> |
| <div class="sect2"> |
| <h3 id="_summary_of_changes_from_opencl_1_0">Summary of changes from OpenCL 1.0</h3> |
| <div class="paragraph"> |
| <p>The following features are added to the OpenCL 1.1 platform layer and |
| runtime (<em>sections 4 and 5</em>):</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Following queries to <em>table 4.3</em></p> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_DEVICE_NATIVE_VECTOR_WIDTH_{CHAR | SHORT | INT | LONG | FLOAT | |
| DOUBLE | HALF}</p> |
| </li> |
| <li> |
| <p>CL_DEVICE_HOST_UNIFIED_MEMORY</p> |
| </li> |
| <li> |
| <p>CL_DEVICE_OPENCL_C_VERSION</p> |
| </li> |
| </ul> |
| </div> |
| </li> |
| <li> |
| <p>CL_CONTEXT_NUM_DEVICES to the list of queries specified to |
| <strong>clGetContextInfo</strong>.</p> |
| </li> |
| <li> |
| <p>Optional image formats: CL_Rx, CL_RGx and CL_RGBx.</p> |
| </li> |
| <li> |
| <p>Support for sub-buffer objects ability to create a buffer object that |
| refers to a specific region in another buffer object using |
| <strong>clCreateSubBuffer</strong>.</p> |
| </li> |
| <li> |
| <p><strong>clEnqueueReadBufferRect</strong>, <strong>clEnqueueWriteBufferRect</strong> and |
| <strong>clEnqueueCopyBufferRect</strong> APIs to read from, write to and copy a |
| rectangular region of a buffer object respectively.</p> |
| </li> |
| <li> |
| <p><strong>clSetMemObjectDestructorCallback</strong> API to allow a user to register a |
| callback function that will be called when the memory object is deleted |
| and its resources freed.</p> |
| </li> |
| <li> |
| <p>Options that <a href="#opencl-c-version">control the OpenCL C version</a> used |
| when building a program executable.</p> |
| </li> |
| <li> |
| <p>CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE to the list of queries |
| specified to <strong>clGetKernelWorkGroupInfo</strong>.</p> |
| </li> |
| <li> |
| <p>Support for user events. |
| User events allow applications to enqueue commands that wait on a user |
| event to finish before the command is executed by the device. |
| Following new APIs are added - <strong>clCreateUserEvent</strong> and |
| <strong>clSetUserEventStatus</strong>.</p> |
| </li> |
| <li> |
| <p><strong>clSetEventCallback</strong> API to register a callback function for a specific |
| command execution status.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The following modifications are made to the OpenCL 1.1 platform layer and |
| runtime (<em>sections 4 and 5</em>):</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Following queries in <em>table 4.3</em></p> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>CL_DEVICE_MAX_PARAMETER_SIZE from 256 to 1024 bytes</p> |
| </li> |
| <li> |
| <p>CL_DEVICE_LOCAL_MEM_SIZE from 16 KB to 32 KB.</p> |
| </li> |
| </ul> |
| </div> |
| </li> |
| <li> |
| <p>The <em>global_work_offset</em> argument in <strong>clEnqueueNDRangeKernel</strong> can be a |
| non-<code>NULL</code> value.</p> |
| </li> |
| <li> |
| <p>All API calls except <strong>clSetKernelArg</strong> are thread-safe.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The following features are added to the OpenCL C programming language |
| (<em>section 6</em>) in OpenCL 1.1:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>3-component vector data types.</p> |
| </li> |
| <li> |
| <p>New built-in functions</p> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>get_global_offset</strong> work-item function defined in section <em>6.12.1</em>.</p> |
| </li> |
| <li> |
| <p><strong>minmag</strong>, <strong>maxmag</strong> math functions defined in section <em>6.12.2</em>.</p> |
| </li> |
| <li> |
| <p><strong>clamp</strong> integer function defined in <em>section 6.12.3</em>.</p> |
| </li> |
| <li> |
| <p>(vector, scalar) variant of integer functions <strong>min</strong> and <strong>max</strong> in |
| <em>section 6.12.3</em>.</p> |
| </li> |
| <li> |
| <p><strong>async_work_group_strided_copy</strong> defined in section <em>6.12.10</em>.</p> |
| </li> |
| <li> |
| <p><strong>vec_step</strong>, <strong>shuffle</strong> and <strong>shuffle2</strong> defined in section <em>6.12.12</em>.</p> |
| </li> |
| </ul> |
| </div> |
| </li> |
| <li> |
| <p><strong>cl_khr_byte_addressable_store</strong> extension is a core feature.</p> |
| </li> |
| <li> |
| <p><strong>cl_khr_global_int32_base_atomics</strong>, |
| <strong>cl_khr_global_int32_extended_atomics</strong>, |
| <strong>cl_khr_local_int32_base_atomics</strong> and |
| <strong>cl_khr_local_int32_extended_atomics</strong> extensions are core features. |
| The built-in atomic function names are changed to use the <strong>atomic_</strong> |
| prefix instead of <strong>atom_</strong>.</p> |
| </li> |
| <li> |
| <p>Macros CL_VERSION_1_0 and CL_VERSION_1_1.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The following features in OpenCL 1.0 are deprecated (see glossary) in OpenCL |
| 1.1:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>The <strong>clSetCommandQueueProperty</strong> API is no longer supported in OpenCL |
| 1.1.</p> |
| </li> |
| <li> |
| <p>The <code>__ROUNDING_MODE__</code> macro is no longer supported in OpenCL C 1.1.</p> |
| </li> |
| <li> |
| <p>The cl-strict-aliasing option that can be specified in <em>options</em> |
| argument to <strong>clBuildProgram</strong> is no longer supported in OpenCL 1.1.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The following new extensions are added to <em>section 9</em> in OpenCL 1.1:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>cl_khr_gl_event</strong> for creating a CL event object from a GL sync object.</p> |
| </li> |
| <li> |
| <p><strong>cl_khr_d3d10_sharing</strong> for sharing memory objects with Direct3D 10.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The following modifications are made to the OpenCL ES Profile described in |
| <em>section 10</em> in OpenCL 1.1:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>64-bit integer support is optional.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_summary_of_changes_from_opencl_1_1">Summary of changes from OpenCL 1.1</h3> |
| <div class="paragraph"> |
| <p>The following features are added to the OpenCL 1.2 platform layer and |
| runtime (<em>sections 4 and 5</em>):</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Custom devices and built-in kernels are supported.</p> |
| </li> |
| <li> |
| <p>Device partitioning that allows a device to be partitioned based on a |
| number of partitioning schemes supported by the device.</p> |
| </li> |
| <li> |
| <p>Extend <em>cl_mem_flags</em> to describe how the host accesses the data in a |
| cl_mem object.</p> |
| </li> |
| <li> |
| <p><strong>clEnqueueFillBuffer</strong> and <strong>clEnqueueFillImage</strong> to support filling a |
| buffer with a pattern or an image with a color.</p> |
| </li> |
| <li> |
| <p>Add CL_MAP_WRITE_INVALIDATE_REGION to <em>cl_map_flags</em>. |
| Appropriate clarification to the behavior of CL_MAP_WRITE has been added |
| to the spec.</p> |
| </li> |
| <li> |
| <p>New image types: 1D image, 1D image from a buffer object, 1D image array |
| and 2D image arrays.</p> |
| </li> |
| <li> |
| <p><strong>clCreateImage</strong> to create an image object.</p> |
| </li> |
| <li> |
| <p><strong>clEnqueueMigrateMemObjects</strong> API that allows a developer to have |
| explicit control over the location of memory objects or to migrate a |
| memory object from one device to another.</p> |
| </li> |
| <li> |
| <p>Support separate compilation and linking of programs.</p> |
| </li> |
| <li> |
| <p>Additional queries to get the number of kernels and kernel names in a |
| program have been added to <strong>clGetProgramInfo</strong>.</p> |
| </li> |
| <li> |
| <p>Additional queries to get the compile and link status and options have |
| been added to <strong>clGetProgramBuildInfo</strong>.</p> |
| </li> |
| <li> |
| <p><strong>clGetKernelArgInfo</strong> API that returns information about the arguments of |
| a kernel.</p> |
| </li> |
| <li> |
| <p><strong>clEnqueueMarkerWithWaitList</strong> and <strong>clEnqueueBarrierWithWaitList</strong> APIs.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The following features are added to the OpenCL C programming language |
| (<em>section 6</em>) in OpenCL 1.2:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Double-precision is now an optional core feature instead of an |
| extension.</p> |
| </li> |
| <li> |
| <p>New built in image types: <strong>image1d_t</strong>, <strong>image1d_array_t</strong> and |
| <strong>image2d_array_t</strong> .</p> |
| </li> |
| <li> |
| <p>New built-in functions</p> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Functions to read from and write to a 1D image, 1D and 2D image arrays |
| described in <em>sections 6.12.14.2</em>, <em>6.12.14.3</em> and <em>6.12.14.4</em>.</p> |
| </li> |
| <li> |
| <p>Sampler-less image read functions described in <em>section 6.12.14.3</em>.</p> |
| </li> |
| <li> |
| <p><strong>popcount</strong> integer function described in <em>section 6.12.3</em>.</p> |
| </li> |
| <li> |
| <p><strong>printf</strong> function described in <em>section 6.12.13</em>.</p> |
| </li> |
| </ul> |
| </div> |
| </li> |
| <li> |
| <p>Storage class specifiers extern and static as described in <em>section |
| 6.8</em>.</p> |
| </li> |
| <li> |
| <p>Macros <code>CL_VERSION_1_2</code> and <code>__OPENCL_C_VERSION__</code>.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The following APIs in OpenCL 1.1 are deprecated (see glossary) in OpenCL |
| 1.2:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>clEnqueueMarker</strong>, <strong>clEnqueueBarrier</strong> and <strong>clEnqueueWaitForEvents</strong></p> |
| </li> |
| <li> |
| <p><strong>clCreateImage2D</strong> and <strong>clCreateImage3D</strong></p> |
| </li> |
| <li> |
| <p><strong>clUnloadCompiler</strong> and <strong>clGetExtensionFunctionAddress</strong></p> |
| </li> |
| <li> |
| <p><strong>clCreateFromGLTexture2D</strong> and <strong>clCreateFromGLTexture3D</strong></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The following queries are deprecated (see glossary) in OpenCL 1.2:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE</strong> in <em>table 4.3</em> queried using |
| <strong>clGetDeviceInfo</strong>.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_summary_of_changes_from_opencl_1_2">Summary of changes from OpenCL 1.2</h3> |
| <div class="paragraph"> |
| <p>The following features are added to the OpenCL 2.0 platform layer and |
| runtime (<em>sections 4 and 5</em>):</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Shared virtual memory.</p> |
| </li> |
| <li> |
| <p>Device queues used to enqueue kernels on the device.</p> |
| </li> |
| <li> |
| <p>Pipes.</p> |
| </li> |
| <li> |
| <p>Images support for 2D image from buffer, depth images and sRGB images.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The following modifications are made to the OpenCL 2.0 platform layer and |
| runtime (sections 4 and 5):</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>All API calls except <strong>clSetKernelArg</strong>, <strong>clSetKernelArgSVMPointer</strong> and |
| <strong>clSetKernelExecInfo</strong> are thread-safe.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The following features are added to the OpenCL C programming language |
| (<em>section 6</em>) in OpenCL 2.0:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Clang Blocks.</p> |
| </li> |
| <li> |
| <p>Kernels enqueing kernels to a device queue.</p> |
| </li> |
| <li> |
| <p>Program scope variables in global address space.</p> |
| </li> |
| <li> |
| <p>Generic address space.</p> |
| </li> |
| <li> |
| <p>C1x atomics.</p> |
| </li> |
| <li> |
| <p>New built-in functions (sections 6.13.9, 6.13.11, 6.13.15 and 6.14).</p> |
| </li> |
| <li> |
| <p>Support images with the read_write qualifier.</p> |
| </li> |
| <li> |
| <p>3D image writes are a core feature.</p> |
| </li> |
| <li> |
| <p>The CL_VERSION_2_0 macro.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The following APIs are deprecated (see glossary) in OpenCL 2.0:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>clCreateCommandQueue</strong>, <strong>clCreateSampler</strong> and <strong>clEnqueueTask</strong></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The following queries are deprecated (see glossary) in OpenCL 2.0:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>CL_DEVICE_HOST_UNIFIED_MEMORY</strong> in <em>table 4.3</em> queried using |
| <strong>clGetDeviceInfo</strong>.</p> |
| </li> |
| <li> |
| <p><strong>CL_IMAGE_BUFFER</strong> in <em>table 5.10</em> is deprecated.</p> |
| </li> |
| <li> |
| <p><strong>CL_DEVICE_QUEUE_PROPERTIES</strong> is replaced by |
| <strong>CL_DEVICE_QUEUE_ON_HOST_PROPERTIES</strong>.</p> |
| </li> |
| <li> |
| <p>The explicit memory fence functions defined in section 6.12.9 of the |
| OpenCL 1.2 specification.</p> |
| </li> |
| <li> |
| <p>The OpenCL 1.2 atomic built-in functions for 32-bit integer and |
| floating-point data types defined in section 6.12.11 of the OpenCL 1.2 |
| specification.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_summary_of_changes_from_opencl_2_0">Summary of changes from OpenCL 2.0</h3> |
| <div class="paragraph"> |
| <p>The following features are added to the OpenCL 2.1 platform layer and |
| runtime (<em>sections 4 and 5</em>):</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>clGetKernelSubGroupInfo</strong> API call.</p> |
| </li> |
| <li> |
| <p><strong>CL_KERNEL_MAX_NUM_SUB_GROUPS</strong>, <strong>CL_KERNEL_COMPILE_NUM_SUB_GROUPS</strong> |
| additions to table 5.21 of the API specification.</p> |
| </li> |
| <li> |
| <p><strong>clCreateProgramWithIL</strong> API call.</p> |
| </li> |
| <li> |
| <p><strong>clGetHostTimer</strong> and <strong>clGetDeviceAndHostTimer</strong> API calls.</p> |
| </li> |
| <li> |
| <p><strong>clEnqueueSVMMigrateMem</strong> API call.</p> |
| </li> |
| <li> |
| <p><strong>clCloneKernel</strong> API call.</p> |
| </li> |
| <li> |
| <p><strong>clSetDefaultDeviceCommandQueue</strong> API call.</p> |
| </li> |
| <li> |
| <p><strong>CL_PLATFORM_HOST_TIMER_RESOLUTION</strong> added to table 4.1 of the API |
| specification.</p> |
| </li> |
| <li> |
| <p><strong>CL_DEVICE_IL_VERSION</strong>, <strong>CL_DEVICE_MAX_NUM_SUB_GROUPS</strong>, |
| <strong>CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS</strong> added to table 4.3 of |
| the API specification.</p> |
| </li> |
| <li> |
| <p><strong>CL_PROGRAM_IL</strong> to table 5.17 of the API specification.</p> |
| </li> |
| <li> |
| <p><strong>CL_QUEUE_DEVICE_DEFAULT</strong> added to table 5.2 of the API specification.</p> |
| </li> |
| <li> |
| <p>Added table 5.22 to the API specification with the enums: |
| <strong>CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE</strong>, |
| <strong>CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE</strong> and |
| <strong>CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT</strong></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The following modifications are made to the OpenCL 2.1 platform layer and |
| runtime (sections 4 and 5):</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>All API calls except <strong>clSetKernelArg</strong>, <strong>clSetKernelArgSVMPointer</strong>, |
| <strong>clSetKernelExecInfo</strong> and <strong>clCloneKernel</strong> are thread-safe.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The OpenCL C kernel language is no longer chapter 6. |
| The OpenCL C kernel language is not updated for OpenCL 2.1. |
| The OpenCL 2.0 kernel language will still be consumed by OpenCL 2.1 |
| runtimes.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The SPIR-V IL specification has been added.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_summary_of_changes_from_opencl_2_1">Summary of changes from OpenCL 2.1</h3> |
| <div class="paragraph"> |
| <p>The following changes have been made to the OpenCL 2.2 execution model |
| (section 3)</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Added the third prerequisite (executing non-trivial constructors for |
| program scope global variables).</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The following features are added to the OpenCL 2.2 platform layer and |
| runtime (<em>sections 4 and 5</em>):</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>clSetProgramSpecializationConstant</strong> API call</p> |
| </li> |
| <li> |
| <p><strong>clSetProgramReleaseCallback</strong> API call</p> |
| </li> |
| <li> |
| <p>Queries for CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT, |
| CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The following modifications are made to the OpenCL 2.2 platform layer and |
| runtime (section 4 and 5):</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Modified description of CL_DEVICE_MAX_CLOCK_FREQUENCY query.</p> |
| </li> |
| <li> |
| <p>Added a new error code CL_MAX_SIZE_RESTRICTION_EXCEEDED to |
| <strong>clSetKernelArg</strong> API call</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Added definition of Deprecation and Specialization constants to the |
| glossary.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div id="footer"> |
| <div id="footer-text"> |
| Version v2.2-10<br> |
| Last updated 2019-02-05 16:03:11 EST |
| </div> |
| </div> |
| |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-MML-AM_HTMLorMML"></script> |
| </body> |
| </html> |