Files
ANSLibs/ANS-HWiNFO/external/OpenCL/lib/SDK.md

278 lines
10 KiB
Markdown
Raw Normal View History

# OpenCL SDK Library
The OpenCL SDK Library hosts both C and C++ utilities which are generally useful for writing OpenCL applications but are either dependency-heavy or contentious. Because these utilities aren't the subject of universal interest, these utilities are _not_ exported, meaning SDK installations won't install their headers nor their libraries. Doing so the [OpenCL Utility Library](./Utils.md) can be kept dependency-free.
The utilities are broken into to libraries, `OpenCLSDK` and `OpenCLSDKCpp`. Samples include `<CL/Utils/Utils.h>`/`<CL/Utils/Utils.hpp>` and link to their libraries respectively.
## List of utilities
- [Command-line Interface](#command-line-interface-utilities)
- [Pseudo Random Number Generation utilities](#pseudo-random-number-generation-utilities)
- [Image utilities](#image-utilities)
- [OpenCL-OpenGL interop utilities](#openCL-openGL-interop-utilities)
### Command-line interface utilities
#### C
```c
struct cl_sdk_options_DeviceTriplet
{
int plat_index;
int dev_index;
cl_device_type dev_type;
};
struct cl_sdk_options_Diagnostic
{
bool verbose;
bool quiet;
};
struct cl_sdk_options_SingleDevice
{
struct cl_sdk_options_DeviceTriplet triplet;
};
struct cl_sdk_options_MultiDevice
{
struct cl_sdk_options_DeviceTriplet * triplets;
size_t number;
};
```
#### C++
```c++
struct cl::sdk::DeviceTriplet
{
int plat_index;
int dev_index;
cl_device_type dev_type;
};
struct cl::sdk::Diagnostic
{
bool verbose,
quiet;
};
struct cl::sdk::SingleDevice
{
DeviceTriplet triplet;
};
struct cl::sdk::MultiDevice
{
cl::vector<DeviceTriplet> triplets;
};
struct cl::sdk::Window
{
int width;
int height;
bool fullscreen;
};
```
The SDK Library deduplicates the storage the result of common CLI argument parsing. These types are used throughout the SDK samples.
#### C++
```c++
template <typename Option>
auto cl::sdk::parse();
template <typename Option, typename... Parsers>
Option cl::sdk::comprehend(Parsers... parsers);
template <typename... Options>
std::tuple<Options...> cl::sdk::parse_cli(int argc, char* argv[], std::string banner = "OpenCL SDK sample template")
```
These functions reduce the boilerplate needed for each sample to introduce their own set of command-line arguments and helps deduplicate the set of common options which most samples inherit.
The first two are the customizable parts where each sample (and the the pre-defined options) specify how CLI arguments should be processed. `cl::sdk::parse()` specifies what the option names are and should return an instance of tuple-like type (`std::get<int>(const type&)` be valid) containing smart-pointer-like types (`ptr.get()` be valid) holding TCLAP arguments and switches. `cl::sdk::comprehend()` takes this tuple already expanded as arguments with names and "makes sense" of the strings of args already validated during parsing and returns a singular struct of the options at hand.
> The types returned by `cl::sdk::parse()` must exactly match the `Parsers...` of `cl::sdk::comprehend()`.
`cl::sdk::parse_cli()` is a simple metaprogram that invokes the `parse` and `comprehend` functions of all the `Options` types it is given in the correct order. First it registers all the command-line arguments and switches, then invokes the parse method of the underlying CLI parser and then invokes the comprehend method of the
Simplest example is the C++ SAXPY sample adding a single option to control the length of the vector operands. The sample uses a single OpenCL device and respects diagnostic level options as well.
#### C++
```c++
// Sample-specific option
struct SaxpyOptions { size_t length; };
// Add option to CLI parsing SDK utility
template <> auto cl::sdk::parse<SaxpyOptions>(){
return std::make_tuple(
std::make_shared<TCLAP::ValueArg<size_t>>("l", "length", "Length of input", false, 1'048'576, "positive integral")
);
}
template <> SaxpyOptions cl::sdk::comprehend<SaxpyOptions>(
std::shared_ptr<TCLAP::ValueArg<size_t>> length_arg){
return SaxpyOptions{
length_arg->getValue()
};
}
int main(int argc, char* argv[])
{
try
{
// Parse command-line options
auto opts = cl::sdk::parse_cli<
cl::sdk::options::Diagnostic,
cl::sdk::options::SingleDevice,
SaxpyOptions>(argc, argv);
const auto& diag_opts = std::get<0>(opts);
const auto& dev_opts = std::get<1>(opts);
const auto& saxpy_opts = std::get<2>(opts);
...
}
// catch clauses
}
```
_(Note: C++17 structured-bindings allows cleaner binding of names to the members of the tuple returned by `cl::sdk::parse_cli`.)_
### Pseudo Random Number Generation utilities
#### C
```c
void cl_sdk_fill_with_random_floats(pcg32_random_t * rng, cl_float * arr, const size_t len);
```
Fills an array with random floats in the range [0, 1).
- `rng` must point to a valid PRNG instance.
- `arr` must be allocated storage long enough to store the results.
- `len` is the count of elements that will be written to `arr`.
```c
void cl_sdk_fill_with_random_floats_range(pcg32_random_t * rng,
cl_float * arr, const size_t len, const cl_float low, const cl_float hi);
```
Fills an array with random floats in the range [`low`, `hi`).
- `rng` must point to a valid PRNG instance.
- `arr` must be allocated storage long enough to store the results.
- `len` is the count of elements that will be written to `arr`.
- `low` is the low-end of the range.
- `hi` is the high-end of the range.
```c
void cl_sdk_fill_with_random_ints_range(pcg32_random_t * rng,
cl_int * arr, const size_t len, const cl_int low, const cl_int hi);
```
Fills an array with uniformly distributed numbers in the range [`low`, `hi`]. Uses rejection sampling from uniform bit distribution.
- `rng` must point to a valid PRNG instance.
- `arr` must be allocated storage long enough to store the results.
- `len` is the count of elements that will be written to `arr`.
- `low` is the low-end of the range.
- `hi` is the high-end of the range.
#### C++
```c++
template <typename PRNG, typename... Containers>
void fill_with_random(PRNG&& prng, Containers&&... containers);
```
Fills containers with random numbers using a user-provided PRNG.
- `prng` must be a PRNG, a callable type with `T(void)` signature where `T` is implicitly convertible to the `value_type` of `containers`.
- `containers` must be a container providing a [LegacyOutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator).
### Image utilities
#### C
```c
typedef struct cl_sdk_image
{
int width, height, pixel_size;
unsigned char* pixels;
}
cl_sdk_image;
```
#### C++
```c++
struct cl::sdk::Image
{
int width, height, pixel_size;
cl::vector<unsigned char> pixels;
};
```
Used to store pixel information of images read/written to/from storage.
- `width` and `height` store the number of pixels the image has in x-y directions respectively.
- `pixel_size` stores the number of bytes used to store a single pixel.
- `pixels` stores the actual pixel data.
#### C
```c
cl_sdk_image cl_sdk_read_image(const char* file_name, cl_int* err);
```
#### C++
```c++
Image cl::sdk::read_image(const char* file_name, cl_int* err);
```
Reads a BMP/JPEG/PNG image from disk.
- `file_name` specifies the absolute or relative path (to the current working-directory) to the image.
- `err` is an optional pointer used to capture error conditions.
Returns an `cl_sdk_image`/`cl::sdk::Image` instance. If an error occurs, the returned image is in an invalid state.
#### C
```c
void cl_sdk_write_image(const char * file_name, const cl_sdk_image * im, cl_int * err);
```
#### C++
```c++
void cl::sdk::write_image(const char* file_name, const Image& image, cl_int* err);
```
Writes a BMP/JPEG/PNG image from disk.
- `file_name` specifies the absolute or relative path (to the current working-directory) to the image.
- `image` is the source of pixel information.
- `err` is an optional pointer used to capture error conditions.
### OpenCL-OpenGL interop utilities
#### C++
```c++
cl::vector<cl_context_properties> cl::sdk::get_interop_context_properties(const cl::Device& plat, cl_int* error = nullptr);
```
This function returns a null-terminated list of context properties required to setup an OpenCL-OpenGL interop context with the currently active OpenGL context.
If `error` is non-null or if `CL_HPP_ENABLE_EXCEPTIONS` is used, ordinary OpenCL error codes may be returned and the following library-specific error codes:
- `CL_UTIL_OS_GL_QUERY_ERROR` if platform-specific errors occur when trying to query for the currently active OpenGL context.
#### C++
```c++
cl::Context cl::sdk::get_interop_context(int plat_id, int dev_id, cl_device_type type, cl_int* error = nullptr);
```
This function creates an interop context on the platform with id `plat_id` with a single device of type `type` and id `dev_id` which is able to share resources with the currently active OpenGL context.
If `error` is non-null or if `CL_HPP_ENABLE_EXCEPTIONS` is used, ordinary OpenCL error codes may be returned and the following library-specific error codes:
- `CL_UTIL_INDEX_OUT_OF_RANGE` if the requested platform or device id is outside the range of available platforms or devices of the selected `type` on the platform.
- `CL_UTIL_OS_GL_QUERY_ERROR` if platform-specific errors occur when trying to query for the currently active OpenGL context.
#### C++
```c++
class cl::sdk::InteropWindow : public sf::Window
{
public:
explicit InteropWindow(
sf::VideoMode mode,
const sf::String& title,
sf::Uint32 style = sf::Style::Default,
const sf::ContextSettings& settings = sf::ContextSettings{},
int platform_id = 0,
int device_id = 0,
cl_bitfield device_type = CL_DEVICE_TYPE_DEFAULT
);
void run();
protected:
// Core functionality to be overriden
virtual void initializeGL() = 0; // Function that initializes all OpenGL assets needed to draw a scene
virtual void initializeCL() = 0; // Function that initializes all OpenCL assets needed to draw a scene
virtual void updateScene() = 0; // Function that holds scene update guaranteed not to conflict with drawing
virtual void render() = 0; // Function that does the native rendering
virtual void event(const sf::Event& e) = 0; // Function that handles render area resize
cl::Context opencl_context;
bool cl_khr_gl_event_supported;
};
```
This class encapsulates an interactive window with the content being one OpenGL canvas. It provides a set of functions for the user to override in derived classes.