blob: 311549b02872ebd8ac291b1fcdfbd443b252fb71 [file] [log] [blame] [edit]
// Copyright 2017-2024 The Khronos Group. This work is licensed under a
// Creative Commons Attribution 4.0 International License; see
// http://creativecommons.org/licenses/by/4.0/
[[extensions-overview]]
== Extensions Overview
_Extensions_ are optional features which may be supported by OpenCL
implementations.
Extensions are not required to be supported by a conformant OpenCL
implementation, but are expected to be widely available, and in some cases
may define functionality that is likely to be required in a future revision
of the OpenCL specification.
In the past, this document contained full specification language for
Khronos-approved `khr` extensions, described in terms of changes to the core
OpenCL Specification.
This extension language has now been integrated into the OpenCL 3.0
Specification, and can be read in context there.
The remaining parts of this document describe general issues in _using_
extensions, such as API <<naming-convention-for-optional-extensions, Naming
Conventions for Optional Extensions>>; OpenCL C
<<compiler-directives-for-optional-extensions, Compiler Directives for
Optional Extensions>>; and <<getting-opencl-api-extension-function-pointers,
Getting OpenCL API Extension Function Pointers>>.
In addition, there is a section on <<spirv_extensions, Extensions to the
OpenCL SPIR-V Environment>>.
Finally, the <<quick-reference, Quick Reference>> appendix summarizes khr
extensions and links to them in the OpenCL API Specification.
In some cases, extensions are mostly or entirely to the OpenCL C language
rather than to the OpenCL API.
Such extensions can be reached by following the links in the API
Specification extension appendices.
[[naming-convention-for-optional-extensions]]
=== Naming Convention for Optional Extensions
OpenCL extensions approved by the OpenCL working group use the following
naming convention:
* A unique _name string_ of the form `"*cl_khr_<__name__>*"` is associated
with each extension.
If the extension is supported by an implementation, this string will be
present in the implementation's `CL_PLATFORM_EXTENSIONS` string or
`CL_DEVICE_EXTENSIONS` string.
* All API functions defined by the extension will have names of the form
*cl<__function_name__>KHR*.
* All enumerants defined by the extension will have names of the form
*CL_<__enum_name__>_KHR.*
Functions and enumerants defined by extensions that are promoted to
core features will have their *KHR* affix removed.
OpenCL implementations of such later revisions must also export the name
strings of promoted extensions in the `CL_PLATFORM_EXTENSIONS` or
`CL_DEVICE_EXTENSIONS` string, and support the *KHR*-affixed versions of
functions and enumerants as a transition aid.
Vendor extensions are strongly encouraged to follow a similar naming
convention:
* A unique _name string_ of the form `"*cl_<__vendor_name__>_<__name>__*"`
is associated with each extension.
If the extension is supported by an implementation, this string will be
present in the implementation's `CL_PLATFORM_EXTENSIONS` string or
`CL_DEVICE_EXTENSIONS` string.
* All API functions defined by the vendor extension will have names of the
form *cl<__function_name__><__vendor_name__>*.
* All enumerants defined by the vendor extension will have names of the
form *CL_<__enum_name__>_<__vendor_name__>.*
[[compiler-directives-for-optional-extensions]]
=== Compiler Directives for Optional Extensions
The *#pragma OPENCL EXTENSION* directive controls the behavior of the OpenCL
compiler with respect to extensions.
The *#pragma OPENCL EXTENSION* directive is defined as:
[source,opencl_c]
----
#pragma OPENCL EXTENSION <extension_name> : <behavior>
#pragma OPENCL EXTENSION all : <behavior>
----
where _extension_name_ is the name of the extension.
The _extension_name_ will have names of the form *cl_khr_<__name__>* for an
extension approved by the OpenCL working group and will have names of the
form *cl_<__vendor_name__>_<__name__>* for vendor extensions.
The token *all* means that the behavior applies to all extensions supported
by the compiler.
The _behavior_ can be set to one of the following values given by the table
below.
[cols="1,3",options="header",]
|====
| *behavior* | *Description*
| *enable*
| Behave as specified by the extension _extension_name_.
Report an error on the *`#pragma OPENCL EXTENSION`* if the
_extension_name_ is not supported, or if *all* is specified.
| *disable*
| Behave (including issuing errors and warnings) as if the extension
_extension_name_ is not part of the language definition.
If *all* is specified, then behavior must revert back to that of the
non-extended core version of the language being compiled to.
Warn on the *`#pragma OPENCL EXTENSION`* if the extension _extension_name_
is not supported.
|====
The *`#pragma OPENCL EXTENSION`* directive is a simple, low-level mechanism
to set the behavior for each extension.
It does not define policies such as which combinations are appropriate;
those must be defined elsewhere.
The order of directives matter in setting the behavior for each extension.
Directives that occur later override those seen earlier.
The *all* variant sets the behavior for all extensions, overriding all
previously issued extension directives, but only if the _behavior_ is set to
*disable*.
The initial state of the compiler is as if the directive
[source,opencl_c]
----
#pragma OPENCL EXTENSION all : disable
----
was issued, telling the compiler that all error and warning reporting must
be done according to this specification, ignoring any extensions.
Every extension which affects the OpenCL language semantics, syntax or adds
built-in functions to the language must create a preprocessor `#define` that
matches the extension name string.
This `#define` would be available in the language if and only if the
extension is supported on a given implementation.
*Example*:
An extension which adds the extension string `"cl_khr_3d_image_writes"`
should also add a preprocessor `#define` called *`cl_khr_3d_image_writes`*.
A kernel can now use this preprocessor `#define` to do something like:
[source,opencl_c]
----
#ifdef cl_khr_3d_image_writes
// do something using the extension
#else
// do something else or #error!
#endif
----
[[getting-opencl-api-extension-function-pointers]]
=== Getting OpenCL API Extension Function Pointers
The function
indexterm:[clGetExtensionFunctionAddressForPlatform]
[source,opencl]
----
void* clGetExtensionFunctionAddressForPlatform(cl_platform_id platform,
const char *funcname)
----
returns the address of the extension function named by _funcname_ for a
given _platform_ The pointer returned should be cast to a function pointer
type matching the extension function's definition defined in the appropriate
extension specification and header file.
A return value of `NULL` indicates that the specified function does not
exist for the implementation or _platform_ is not a valid platform.
A non-`NULL` return value for *clGetExtensionFunctionAddressForPlatform*
does not guarantee that an extension function is actually supported by the
platform.
The application must also make a corresponding query using
*clGetPlatformInfo*(platform, CL_PLATFORM_EXTENSIONS, ...) or
*clGetDeviceInfo*(device, CL_DEVICE_EXTENSIONS, ...) to determine if an
extension is supported by the OpenCL implementation.
Since there is no way to qualify the query with a
device, the function pointer returned must work for all implementations of
that extension on different devices for a platform.
The behavior of calling a device extension function on a device not
supporting that extension is undefined.
*clGetExtensionFunctionAddressForPlatform* may not be be used to query for core
(non-extension) functions in OpenCL.
For extension functions that may be queried using
*clGetExtensionFunctionAddressForPlatform*, implementations may also choose to
export those functions statically from the object libraries
implementing those functions, however, portable applications cannot rely on
this behavior.
Function pointer typedefs must be declared for all extensions that add API
entrypoints.
These typedefs are a required part of the extension interface, to be
provided in an appropriate header (such as cl_ext.h if the extension is an
OpenCL extension, or cl_gl_ext.h if the extension is an OpenCL / OpenGL
sharing extension).
The following convention must be followed for all extensions affecting the
host API:
[source,opencl]
----
#ifndef extension_name
#define extension_name 1
// all data typedefs, token #defines, prototypes, and
// function pointer typedefs for this extension
// function pointer typedefs must use the
// following naming convention
typedef return_type
(CL_API_CALL *clExtensionFunctionNameTAG_fn)(...);
#endif // _extension_name_
----
where `TAG` can be `KHR`, `EXT` or `vendor-specific`.
Consider, for example, the *cl_khr_gl_sharing* extension.
This extension would add the following to cl_gl_ext.h:
[source,opencl]
----
#ifndef cl_khr_gl_sharing
#define cl_khr_gl_sharing 1
// all data typedefs, token #defines, prototypes, and
// function pointer typedefs for this extension
#define CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR -1000
#define CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR 0x2006
#define CL_DEVICES_FOR_GL_CONTEXT_KHR 0x2007
#define CL_GL_CONTEXT_KHR 0x2008
#define CL_EGL_DISPLAY_KHR 0x2009
#define CL_GLX_DISPLAY_KHR 0x200A
#define CL_WGL_HDC_KHR 0x200B
#define CL_CGL_SHAREGROUP_KHR 0x200C
// function pointer typedefs must use the
// following naming convention
typedef cl_int
(CL_API_CALL *clGetGLContextInfoKHR_fn)(
const cl_context_properties * /* properties */,
cl_gl_context_info /* param_name */,
size_t /* param_value_size */,
void * /* param_value */,
size_t * /*param_value_size_ret*/);
#endif // cl_khr_gl_sharing
----