diff options
author | Denis Steckelmacher <steckdenis@yahoo.fr> | 2011-08-19 13:47:20 +0200 |
---|---|---|
committer | Denis Steckelmacher <steckdenis@yahoo.fr> | 2011-08-19 13:47:20 +0200 |
commit | 89b835febf6836c517a5890a4e371afed7a173d6 (patch) | |
tree | 1a1e67db3c5bbfb16e92495e2a8354622f69857e | |
parent | 4de220c56f5812f42cc936b805ba94fa67dcbfe7 (diff) |
Document API files, .cpp files and deviceinterface.h
30 files changed, 354 insertions, 4 deletions
diff --git a/doc/llvm.dox b/doc/llvm.dox index fb662ca..8de776a 100644 --- a/doc/llvm.dox +++ b/doc/llvm.dox @@ -17,7 +17,7 @@ * * Once the \c Coal::Program objects holds the source, \c clBuildProgram() can be used to compile it. It does so by invoking \c Coal::Program::build(). * - * This big function compiles and links the program, so it will be explained later. The actual compilation job is done by \c Coal::Compiler. It does that in \c Coal::Compiler::compile, and then keeps the compilation log and options at hand for future use. + * This big function compiles and links the program, so it will be explained later. The actual compilation job is done by \c Coal::Compiler. It does that in \c Coal::Compiler::compile(), and then keeps the compilation log and options at hand for future use. * * When a program is compiled, the client application can retrieve it by using \c clGetProgramInfo(). * @@ -27,7 +27,7 @@ * * The separation between the unlinked binary and the linked one is the reason for the existence of \c Coal::Program::DeviceDependent::unlinked_binary. The source is compiled to LLVM IR in a module (temporarily stored in linked_module, though it isn't linked yet), that is dumped to unlinked_binary and then linked to form a full executable program. * - * So, \c Coal::Program::build() runs its code for every device for which a program must be built. These devices are either given at \c Coal::Program::loadBinaries, or as arguments to \c Coal::Program::build(). + * So, \c Coal::Program::build() runs its code for every device for which a program must be built. These devices are either given at \c Coal::Program::loadBinaries(), or as arguments to \c Coal::Program::build(). * * The first step is to see if the program was loaded with sources. If it's the case, they have to be compiled (see \ref compilation). * @@ -37,7 +37,7 @@ * * Then, the device is allowed to add more optimization or analysis passes. \c Coal::CPUProgram::createOptimizationPasses() adds standard link-time optimizations, but hardware-accelerated devices could add autovectorizing, lowering, or analysis passes. * - * Finally, \c Coal::DeviceProgram::build is called. It's a no-op function for \c Coal::CPUDevice as it uses directly the module with a LLVM JIT, but hardware devices could use this function to actually compile the program for the target device (LLVM to TGSI transformation for example). + * Finally, \c Coal::DeviceProgram::build() is called. It's a no-op function for \c Coal::CPUDevice as it uses directly the module with a LLVM JIT, but hardware devices could use this function to actually compile the program for the target device (LLVM to TGSI transformation for example). * * The program is now built and ready to be usable ! * diff --git a/src/api/api_command.cpp b/src/api/api_command.cpp index 978616a..1a0dd99 100644 --- a/src/api/api_command.cpp +++ b/src/api/api_command.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file api_command.cpp + * \brief Command queues + */ + #include <core/commandqueue.h> #include <core/deviceinterface.h> #include <core/context.h> diff --git a/src/api/api_context.cpp b/src/api/api_context.cpp index 8ebbe4a..fea7d5b 100644 --- a/src/api/api_context.cpp +++ b/src/api/api_context.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file api_context.cpp + * \brief Contexts + */ + #include <CL/cl.h> #include <core/context.h> diff --git a/src/api/api_device.cpp b/src/api/api_device.cpp index 1cd5020..4731a53 100644 --- a/src/api/api_device.cpp +++ b/src/api/api_device.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file api_device.cpp + * \brief Devices + */ + #include "CL/cl.h" #include <core/cpu/device.h> diff --git a/src/api/api_enqueue.cpp b/src/api/api_enqueue.cpp index e4f062a..21501ff 100644 --- a/src/api/api_enqueue.cpp +++ b/src/api/api_enqueue.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file api_enqueue.cpp + * \brief Events + */ + #include <CL/cl.h> #include <core/events.h> diff --git a/src/api/api_event.cpp b/src/api/api_event.cpp index 166a019..5edeb59 100644 --- a/src/api/api_event.cpp +++ b/src/api/api_event.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file api_event.cpp + * \brief Special events and event management + */ + #include <CL/cl.h> #include <core/commandqueue.h> diff --git a/src/api/api_flush.cpp b/src/api/api_flush.cpp index 584dfd0..723ccc7 100644 --- a/src/api/api_flush.cpp +++ b/src/api/api_flush.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file api_flush.cpp + * \brief clFlush and clFinish + */ + #include "CL/cl.h" #include "core/commandqueue.h" diff --git a/src/api/api_gl.cpp b/src/api/api_gl.cpp index 334d983..9084f24 100644 --- a/src/api/api_gl.cpp +++ b/src/api/api_gl.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file api_gl.cpp + * \brief OpenGL bindings (unimplemented) + */ + #define GL_GLEXT_PROTOTYPES #include "GL/gl.h" #include "GL/glext.h" diff --git a/src/api/api_kernel.cpp b/src/api/api_kernel.cpp index ec9aaf7..6e97912 100644 --- a/src/api/api_kernel.cpp +++ b/src/api/api_kernel.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file api_kernel.cpp + * \brief Kernels + */ + #include "CL/cl.h" #include <core/program.h> diff --git a/src/api/api_memory.cpp b/src/api/api_memory.cpp index c3df0f9..94e109e 100644 --- a/src/api/api_memory.cpp +++ b/src/api/api_memory.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file api_memory.cpp + * \brief Memory objects + */ + #include "CL/cl.h" #include <core/memobject.h> #include <core/context.h> diff --git a/src/api/api_platform.cpp b/src/api/api_platform.cpp index 6f01590..f24a183 100644 --- a/src/api/api_platform.cpp +++ b/src/api/api_platform.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file api_platform.cpp + * \brief Platform + */ + #include "CL/cl.h" #include <cstring> #include <core/config.h> diff --git a/src/api/api_profiling.cpp b/src/api/api_profiling.cpp index 861ebff..b37332e 100644 --- a/src/api/api_profiling.cpp +++ b/src/api/api_profiling.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file api_profiling.cpp + * \brief Profiling of events + */ + #include "CL/cl.h" #include <core/commandqueue.h> diff --git a/src/api/api_program.cpp b/src/api/api_program.cpp index d8d5ceb..8e89989 100644 --- a/src/api/api_program.cpp +++ b/src/api/api_program.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file api_program.cpp + * \brief Programs + */ + #include "CL/cl.h" #include <core/program.h> #include <core/context.h> diff --git a/src/api/api_sampler.cpp b/src/api/api_sampler.cpp index 7cced18..62edd43 100644 --- a/src/api/api_sampler.cpp +++ b/src/api/api_sampler.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file api_sampler.cpp + * \brief Samplers + */ + #include "CL/cl.h" #include "core/sampler.h" diff --git a/src/core/commandqueue.cpp b/src/core/commandqueue.cpp index 5321f45..f86cb09 100644 --- a/src/core/commandqueue.cpp +++ b/src/core/commandqueue.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file commandqueue.cpp + * \brief Command queue + */ + #include "commandqueue.h" #include "context.h" #include "deviceinterface.h" diff --git a/src/core/compiler.cpp b/src/core/compiler.cpp index fba0af1..48e2bcf 100644 --- a/src/core/compiler.cpp +++ b/src/core/compiler.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file compiler.cpp + * \brief Compiler wrapper around Clang + */ + #include "compiler.h" #include <cstring> diff --git a/src/core/context.cpp b/src/core/context.cpp index f409198..fa29555 100644 --- a/src/core/context.cpp +++ b/src/core/context.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file context.cpp + * \brief Context + */ + #include "context.h" #include "deviceinterface.h" #include "propertylist.h" diff --git a/src/core/cpu/buffer.cpp b/src/core/cpu/buffer.cpp index 9044903..daba293 100644 --- a/src/core/cpu/buffer.cpp +++ b/src/core/cpu/buffer.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file cpu/buffer.cpp + * \brief CPU buffer + */ + #include "buffer.h" #include "device.h" diff --git a/src/core/cpu/builtins.cpp b/src/core/cpu/builtins.cpp index f4854ec..aacd649 100644 --- a/src/core/cpu/builtins.cpp +++ b/src/core/cpu/builtins.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file cpu/builtins.cpp + * \brief Native OpenCL C built-in functions + */ + #include "builtins.h" #include "kernel.h" #include "buffer.h" diff --git a/src/core/cpu/device.cpp b/src/core/cpu/device.cpp index 42c31bf..545804f 100644 --- a/src/core/cpu/device.cpp +++ b/src/core/cpu/device.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file cpu/device.cpp + * \brief CPU Device + */ + #include "device.h" #include "buffer.h" #include "kernel.h" diff --git a/src/core/cpu/kernel.cpp b/src/core/cpu/kernel.cpp index 049ae0b..94a4a2c 100644 --- a/src/core/cpu/kernel.cpp +++ b/src/core/cpu/kernel.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file cpu/kernel.cpp + * \brief CPU kernel + */ + #include "kernel.h" #include "device.h" #include "buffer.h" diff --git a/src/core/cpu/program.cpp b/src/core/cpu/program.cpp index 9132163..911415c 100644 --- a/src/core/cpu/program.cpp +++ b/src/core/cpu/program.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file cpu/program.cpp + * \brief CPU program + */ + #include "program.h" #include "device.h" #include "kernel.h" diff --git a/src/core/cpu/worker.cpp b/src/core/cpu/worker.cpp index a67c832..9b4fd55 100644 --- a/src/core/cpu/worker.cpp +++ b/src/core/cpu/worker.cpp @@ -25,6 +25,12 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file cpu/worker.cpp + * \brief Code running in the worker threads launched by \c Coal::CPUDevice + * \sa builtins.cpp + */ + #include "worker.h" #include "device.h" #include "buffer.h" diff --git a/src/core/deviceinterface.h b/src/core/deviceinterface.h index 591c097..09ea621 100644 --- a/src/core/deviceinterface.h +++ b/src/core/deviceinterface.h @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file deviceinterface.h + * \brief Abstraction layer between Clover core and the devices + */ + #ifndef __DEVICEINTERFACE_H__ #define __DEVICEINTERFACE_H__ @@ -50,65 +55,269 @@ class Event; class Program; class Kernel; +/** + * \brief Abstraction layer between core Clover objects and the devices + * + * This interface is used by the core Clover classes to communicate with the + * devices, that must reimplement all the functions described here. + */ class DeviceInterface : public Object { public: DeviceInterface() : Object(Object::T_Device, 0) {} virtual ~DeviceInterface() {} + /** + * \brief Retrieve information about the device + * + * This function is used to retrieve information about an object. + * Sometimes, the size of the data retrieved is unknown (for example, a + * string). The application can call this function twice, the first time + * to get the size, then it allocates a buffer, and finally get the data. + * + * \code + * const char *string = 0; + * size_t len; + * + * object->info(FOO_PROPERTY_STRING, 0, 0, &len); + * string = std::malloc(len); + * object->info(FOO_PROPERTY_STRING, len, string, 0); + * \endcode + * + * \param param_name Name of the property to retrieve + * \param param_value_size Size of the application-allocated buffer + * in which to put the value. + * \param param_value Pointer to an application-allocated buffer + * where the property data will be stored. Ignored + * if NULL. + * \param param_value_size_ret Size of the value retrieved, ignored if + * NULL. + * \return CL_SUCCESS in case of success, otherwise a CL error code. + */ virtual cl_int info(cl_device_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret) const = 0; + /** + * \brief Create a \c Coal::DeviceBuffer object for this device + * \param buffer Memory object for which the buffer has to be created + * \param rs Error code (\c CL_SUCCESS if no error) + * \return a \c Coal::DeviceBuffer object, undefined if there is an error + */ virtual DeviceBuffer *createDeviceBuffer(MemObject *buffer, cl_int *rs) = 0; + + /** + * \brief Create a \c Coal::DeviceProgram object for this device + * \param program \c Coal::Program containing the device-independent + * program data + * \return a \c Coal::DeviceProgram object + */ virtual DeviceProgram *createDeviceProgram(Program *program) = 0; + + /** + * \brief Create a \c Coal::DeviceKernel object for this device + * \param kernel \c Coal::Kernel containing the device-independent kernel + * data + * \param function device-specific \c llvm::Function to be used + * \return a \c Coal::DeviceKernel object + */ virtual DeviceKernel *createDeviceKernel(Kernel *kernel, llvm::Function *function) = 0; + /** + * \brief Push an event on the device + * \sa the end of \ref events + * \param event the event to be pushed + */ virtual void pushEvent(Event *event) = 0; - /** @note must set mapping address of MapBuffer events */ + /** + * \brief Initialize device-specific event data + * + * This call allows a device to initialize device-specific event data, + * by using \c Coal::Event::setDeviceData(). For instance, an + * hardware-accelerated device can associate a device command to an + * event, and use it to manage the event when it gets pushed. + * + * @note This function has one obligation: it must call + * \c Coal::MapBufferEvent::setPtr() and + * \c Coal::MapImageEvent::setPtr() (and other function described + * in its documentation) + * + * \param event the event for which data can be set + * \return CL_SUCCESS in case of success + */ virtual cl_int initEventDeviceData(Event *event) = 0; + + /** + * \brief Free device-specific event data + * + * This function is called just before \p event gets deleted. It allows + * a device to free device-specific data of this event, if any. + * + * \param event the event that will be destroyed + */ virtual void freeEventDeviceData(Event *event) = 0; }; +/** + * \brief Device-specific memory buffer + * + * This class is the backing-store used on a device for a \c Coal::MemObject. It + * is created by \c Coal::DeviceInterface::createDeviceBuffer(). + */ class DeviceBuffer { public: DeviceBuffer() {} virtual ~DeviceBuffer() {} + /** + * \brief Allocate the buffer on the device + * \return true when success, false otherwise + */ virtual bool allocate() = 0; + /** + * \brief \c Coal::DeviceInterface of this buffer + * \return parent \c Coal::DeviceInterface + */ virtual DeviceInterface *device() const = 0; + + /** + * \brief Allocation status + * \return true if already allocated, false otherwise + */ virtual bool allocated() const = 0; + /** + * \brief Host-accessible memory pointer + * + * This function returns what is passed as arguments to native kernels + * (\c clEnqueueNativeKernel(), \c Coal::NativeKernelEvent) in place of + * \c Coal::MemObject pointers. + * + * For \c Coal::CPUDevice, it's simply a pointer in RAM, but + * hardware-accelerated devices may need to do some copying or mapping. + * + * \warning Beware that this data may get written to by the native kernel. + * + * \return A memory pointer usable by a host native kernel + */ virtual void *nativeGlobalPointer() const = 0; }; +/** + * \brief Device-specific program data + */ class DeviceProgram { public: DeviceProgram() {} virtual ~DeviceProgram() {} + /** + * \brief Linking or not \b stdlib with this program + * + * \b stdlib is a LLVM bitcode file containing some implementations of + * OpenCL C built-ins. This function allows a device to tell + * \c Coal::Program::build() if it wants \b stdlib to be linked or not. + * + * Linking the library may allow inlining of functions like \c ceil(), + * \c floor(), \c clamp(), etc. So, if these functions are not better + * handled by the device itself than by \b stdlib, it's a good thing + * to link it. + * + * But if the device provides instructions for these functions, then + * it could be better not to link \b stdlib and to replace the LLVM + * calls to these functions with device-specific instructions. + * + * \warning \b Stdlib currently only works for \c Coal::CPUDevice, as + * it contains host-specific code (LLVM IR is not meant to be + * portable, pointer size changes for example). + * + * \return true if \b stdlib must be linked with the program + */ virtual bool linkStdLib() const = 0; + + /** + * \brief Create device-specific optimization passes + * + * This hook allows a device to add LLVM optimization passes to a + * \c llvm::PassManager . This way, devices needing function flattening + * or special analysis passes can have them run on the mode. + * + * \param manager \c llvm::PassManager to which add the passes + * \param optimize false if \c -cl-opt-disable was given at compilation + * time. + */ virtual void createOptimizationPasses(llvm::PassManager *manager, bool optimize) = 0; + + /** + * \brief Build a device-specific representation of the program + * + * This function is called by \c Coal::Program::build() when the module + * is compiled and linked. It can be used by the device to build a + * device-specific representation of the program. + * + * \param module \c llvm::Module containing the program's LLVM IR + * \return true in case of success, false otherwise + */ virtual bool build(llvm::Module *module) = 0; }; +/** + * \brief Device-specific kernel data + */ class DeviceKernel { public: DeviceKernel() {} virtual ~DeviceKernel() {} + /** + * \brief Maximum work-group size of a kernel + * \return Maximum work-group size of the kernel based on device-specific + * data such as memory usage, register pressure, etc) + */ virtual size_t workGroupSize() const = 0; + + /** + * \brief Local memory used by the kernel + * \return Local memory used by the kernel, in bytes + */ virtual cl_ulong localMemSize() const = 0; + + /** + * \brief Private memory used by the kernel + * \return Private memory used by the kernel, in bytes + */ virtual cl_ulong privateMemSize() const = 0; + + /** + * \brief Preferred work-group size multiple + * \return The size multiple a work-group can have to work the best and + * the fastest on the device + */ virtual size_t preferredWorkGroupSizeMultiple() const = 0; + + /** + * \brief Optimal work-group size + * + * This function allows a device to calculate the optimal work-group size + * for this kernel, using it's memory usage, SIMD dimension, etc. + * + * \c Coal::CPUDevice tries to split the kernel into a number of + * work-groups the closest possible to the number of CPU cores. + * + * \param num_dims Number of working dimensions + * \param dim Dimension for which the multiple is being calculated + * \param global_work_size Total number of work-items to split into + * work-groups + * \return optimal size of a work-group, for the \p dim dimension. + */ virtual size_t guessWorkGroupSize(cl_uint num_dims, cl_uint dim, size_t global_work_size) const = 0; }; diff --git a/src/core/events.cpp b/src/core/events.cpp index 3722ea0..da1add2 100644 --- a/src/core/events.cpp +++ b/src/core/events.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file events.cpp + * \brief Events inheriting \c Coal::Event + */ + #include "events.h" #include "commandqueue.h" #include "memobject.h" diff --git a/src/core/kernel.cpp b/src/core/kernel.cpp index 9068d23..b2be86a 100644 --- a/src/core/kernel.cpp +++ b/src/core/kernel.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file core/kernel.cpp + * \brief Kernel + */ + #include "kernel.h" #include "propertylist.h" #include "program.h" diff --git a/src/core/memobject.cpp b/src/core/memobject.cpp index 2b27ea0..47e1141 100644 --- a/src/core/memobject.cpp +++ b/src/core/memobject.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file memobject.cpp + * \brief Memory objects + */ + #include "memobject.h" #include "context.h" #include "deviceinterface.h" diff --git a/src/core/object.cpp b/src/core/object.cpp index 212ddc3..43c5bec 100644 --- a/src/core/object.cpp +++ b/src/core/object.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file object.cpp + * \brief Reference-counted object tree + */ + #include "object.h" using namespace Coal; diff --git a/src/core/program.cpp b/src/core/program.cpp index 72c7553..1dc7d62 100644 --- a/src/core/program.cpp +++ b/src/core/program.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file core/program.cpp + * \brief Program + */ + #include "program.h" #include "context.h" #include "compiler.h" diff --git a/src/core/sampler.cpp b/src/core/sampler.cpp index 9e653e4..8895bd0 100644 --- a/src/core/sampler.cpp +++ b/src/core/sampler.cpp @@ -25,6 +25,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \file sampler.cpp + * \brief Sampler + */ + #include "sampler.h" #include "context.h" #include "deviceinterface.h" |