#pragma once #include #include #include #include #include "Vector4.hpp" #include #include #ifdef linux #include #include #include #elif defined _WIN32 #define CL_USE_DEPRECATED_OPENCL_1_2_APIS #include #include #include // Note: windows.h must be included before Gl/GL.h #include #include #elif defined TARGET_OS_MAC #include #endif class OpenCL { public: OpenCL(); ~OpenCL(); // command queues are associated with a device and context, so for multi-gpu applications you would need // multiple command queues // CONTEXTS // - 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. // - Contexts cannot be created using more than one platform! bool init(); bool compile_kernel(std::string kernel_path, std::string kernel_name); // Create an image buffer from an SF texture. Access Type is the read/write specifier required by OpenCL bool create_image_buffer_from_texture(std::string buffer_name, sf::Texture* texture, cl_int access_type); // Have CL create and manage the texture for the image buffer. Access Type is the read/write specifier required by OpenCL bool create_image_buffer(std::string buffer_name, sf::Vector2i size, sf::Vector2f position, cl_int access_type); bool map_buffer(std::string buffer_name, unsigned int size, void* data = nullptr); // Create a buffer with CL_MEM_READ_ONLY and CL_MEM_COPY_HOST_PTR int create_buffer(std::string buffer_name, cl_uint size, void* data); // Create a buffer with user defined data access flags int create_buffer(std::string buffer_name, cl_uint size, void* data, cl_mem_flags flags); int set_kernel_arg(std::string kernel_name, int index, std::string buffer_name); void run_kernel(std::string kernel_name, sf::Vector2i work_size); void draw(sf::RenderWindow *window); class device { public: #pragma pack(push, 1) struct packed_data { cl_device_type device_type; cl_uint clock_frequency; char opencl_version[64]; cl_uint compute_units; char device_extensions[1024]; char device_name[256]; char platform_name[128]; }; #pragma pack(pop) device(cl_device_id device_id, cl_platform_id platform_id); device(const device& d); void print(std::ostream& stream) const; void print_packed_data(std::ostream& stream); cl_device_id getDeviceId() const { return device_id; }; cl_platform_id getPlatformId() const { return platform_id; }; private: packed_data data; cl_device_id device_id; cl_platform_id platform_id; cl_bool is_little_endian = false; bool cl_gl_sharing = false; }; private: int error = 0; // The device which we have selected according to certain criteria cl_platform_id platform_id; cl_device_id device_id; // The GL shared context and its subsiquently generated command queue cl_context context; cl_command_queue command_queue; // Maps which contain a mapping from "name" to the host side CL memory object std::unordered_map kernel_map; std::unordered_map buffer_map; std::unordered_map>> image_map; std::vector device_list; // Query the hardware on this machine and store the devices bool aquire_hardware(); // After aquiring hardware, create a shared context using platform specific CL commands bool create_shared_context(); // Command queues must be created with a valid context bool create_command_queue(); // Store a cl_mem object in the buffer map bool store_buffer(cl_mem buffer, std::string buffer_name); // Using CL release the memory object and remove the KVP associated with the buffer name bool release_buffer(std::string buffer_name); bool load_config(); void save_config(); static bool vr_assert(int error_code, std::string function_name); };