651 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			651 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								//---------------------------------------------------------------------------//
							 | 
						||
| 
								 | 
							
								// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Distributed under the Boost Software License, Version 1.0
							 | 
						||
| 
								 | 
							
								// See accompanying file LICENSE_1_0.txt or copy at
							 | 
						||
| 
								 | 
							
								// http://www.boost.org/LICENSE_1_0.txt
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// See http://boostorg.github.com/compute for more information.
							 | 
						||
| 
								 | 
							
								//---------------------------------------------------------------------------//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef BOOST_COMPUTE_PROGRAM_HPP
							 | 
						||
| 
								 | 
							
								#define BOOST_COMPUTE_PROGRAM_HPP
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <string>
							 | 
						||
| 
								 | 
							
								#include <vector>
							 | 
						||
| 
								 | 
							
								#include <fstream>
							 | 
						||
| 
								 | 
							
								#include <streambuf>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef BOOST_COMPUTE_DEBUG_KERNEL_COMPILATION
							 | 
						||
| 
								 | 
							
								#include <iostream>
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/compute/config.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/compute/context.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/compute/exception.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/compute/detail/assert_cl_success.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
							 | 
						||
| 
								 | 
							
								#include <sstream>
							 | 
						||
| 
								 | 
							
								#include <boost/optional.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/compute/platform.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/compute/detail/getenv.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/compute/detail/path.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/compute/detail/sha1.hpp>
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace boost {
							 | 
						||
| 
								 | 
							
								namespace compute {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class kernel;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/// \class program
							 | 
						||
| 
								 | 
							
								/// \brief A compute program.
							 | 
						||
| 
								 | 
							
								///
							 | 
						||
| 
								 | 
							
								/// The program class represents an OpenCL program.
							 | 
						||
| 
								 | 
							
								///
							 | 
						||
| 
								 | 
							
								/// Program objects are created with one of the static \c create_with_*
							 | 
						||
| 
								 | 
							
								/// functions. For example, to create a program from a source string:
							 | 
						||
| 
								 | 
							
								///
							 | 
						||
| 
								 | 
							
								/// \snippet test/test_program.cpp create_with_source
							 | 
						||
| 
								 | 
							
								///
							 | 
						||
| 
								 | 
							
								/// And to create a program from a source file:
							 | 
						||
| 
								 | 
							
								/// \code
							 | 
						||
| 
								 | 
							
								/// boost::compute::program bar_program =
							 | 
						||
| 
								 | 
							
								///     boost::compute::program::create_with_source_file("/path/to/bar.cl", context);
							 | 
						||
| 
								 | 
							
								/// \endcode
							 | 
						||
| 
								 | 
							
								///
							 | 
						||
| 
								 | 
							
								/// Once a program object has been succesfully created, it can be compiled
							 | 
						||
| 
								 | 
							
								/// using the \c build() method:
							 | 
						||
| 
								 | 
							
								/// \code
							 | 
						||
| 
								 | 
							
								/// // build the program
							 | 
						||
| 
								 | 
							
								/// foo_program.build();
							 | 
						||
| 
								 | 
							
								/// \endcode
							 | 
						||
| 
								 | 
							
								///
							 | 
						||
| 
								 | 
							
								/// Once the program is built, \ref kernel objects can be created using the
							 | 
						||
| 
								 | 
							
								/// \c create_kernel() method by passing their name:
							 | 
						||
| 
								 | 
							
								/// \code
							 | 
						||
| 
								 | 
							
								/// // create a kernel from the compiled program
							 | 
						||
| 
								 | 
							
								/// boost::compute::kernel foo_kernel = foo_program.create_kernel("foo");
							 | 
						||
| 
								 | 
							
								/// \endcode
							 | 
						||
| 
								 | 
							
								///
							 | 
						||
| 
								 | 
							
								/// \see kernel
							 | 
						||
| 
								 | 
							
								class program
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								    /// Creates a null program object.
							 | 
						||
| 
								 | 
							
								    program()
							 | 
						||
| 
								 | 
							
								        : m_program(0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Creates a program object for \p program. If \p retain is \c true,
							 | 
						||
| 
								 | 
							
								    /// the reference count for \p program will be incremented.
							 | 
						||
| 
								 | 
							
								    explicit program(cl_program program, bool retain = true)
							 | 
						||
| 
								 | 
							
								        : m_program(program)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if(m_program && retain){
							 | 
						||
| 
								 | 
							
								            clRetainProgram(m_program);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Creates a new program object as a copy of \p other.
							 | 
						||
| 
								 | 
							
								    program(const program &other)
							 | 
						||
| 
								 | 
							
								        : m_program(other.m_program)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if(m_program){
							 | 
						||
| 
								 | 
							
								            clRetainProgram(m_program);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Copies the program object from \p other to \c *this.
							 | 
						||
| 
								 | 
							
								    program& operator=(const program &other)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if(this != &other){
							 | 
						||
| 
								 | 
							
								            if(m_program){
							 | 
						||
| 
								 | 
							
								                clReleaseProgram(m_program);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            m_program = other.m_program;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if(m_program){
							 | 
						||
| 
								 | 
							
								                clRetainProgram(m_program);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return *this;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
							 | 
						||
| 
								 | 
							
								    /// Move-constructs a new program object from \p other.
							 | 
						||
| 
								 | 
							
								    program(program&& other) BOOST_NOEXCEPT
							 | 
						||
| 
								 | 
							
								        : m_program(other.m_program)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        other.m_program = 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Move-assigns the program from \p other to \c *this.
							 | 
						||
| 
								 | 
							
								    program& operator=(program&& other) BOOST_NOEXCEPT
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if(m_program){
							 | 
						||
| 
								 | 
							
								            clReleaseProgram(m_program);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        m_program = other.m_program;
							 | 
						||
| 
								 | 
							
								        other.m_program = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return *this;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Destroys the program object.
							 | 
						||
| 
								 | 
							
								    ~program()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if(m_program){
							 | 
						||
| 
								 | 
							
								            BOOST_COMPUTE_ASSERT_CL_SUCCESS(
							 | 
						||
| 
								 | 
							
								                clReleaseProgram(m_program)
							 | 
						||
| 
								 | 
							
								            );
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Returns the underlying OpenCL program.
							 | 
						||
| 
								 | 
							
								    cl_program& get() const
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return const_cast<cl_program &>(m_program);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Returns the source code for the program.
							 | 
						||
| 
								 | 
							
								    std::string source() const
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return get_info<std::string>(CL_PROGRAM_SOURCE);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Returns the binary for the program.
							 | 
						||
| 
								 | 
							
								    std::vector<unsigned char> binary() const
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        size_t binary_size = get_info<size_t>(CL_PROGRAM_BINARY_SIZES);
							 | 
						||
| 
								 | 
							
								        std::vector<unsigned char> binary(binary_size);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        unsigned char *binary_ptr = &binary[0];
							 | 
						||
| 
								 | 
							
								        cl_int error = clGetProgramInfo(m_program,
							 | 
						||
| 
								 | 
							
								                                        CL_PROGRAM_BINARIES,
							 | 
						||
| 
								 | 
							
								                                        sizeof(unsigned char **),
							 | 
						||
| 
								 | 
							
								                                        &binary_ptr,
							 | 
						||
| 
								 | 
							
								                                        0);
							 | 
						||
| 
								 | 
							
								        if(error != CL_SUCCESS){
							 | 
						||
| 
								 | 
							
								            BOOST_THROW_EXCEPTION(opencl_error(error));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return binary;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    std::vector<device> get_devices() const
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        std::vector<cl_device_id> device_ids =
							 | 
						||
| 
								 | 
							
								            get_info<std::vector<cl_device_id> >(CL_PROGRAM_DEVICES);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        std::vector<device> devices;
							 | 
						||
| 
								 | 
							
								        for(size_t i = 0; i < device_ids.size(); i++){
							 | 
						||
| 
								 | 
							
								            devices.push_back(device(device_ids[i]));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return devices;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Returns the context for the program.
							 | 
						||
| 
								 | 
							
								    context get_context() const
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return context(get_info<cl_context>(CL_PROGRAM_CONTEXT));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Returns information about the program.
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// \see_opencl_ref{clGetProgramInfo}
							 | 
						||
| 
								 | 
							
								    template<class T>
							 | 
						||
| 
								 | 
							
								    T get_info(cl_program_info info) const
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return detail::get_object_info<T>(clGetProgramInfo, m_program, info);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// \overload
							 | 
						||
| 
								 | 
							
								    template<int Enum>
							 | 
						||
| 
								 | 
							
								    typename detail::get_object_info_type<program, Enum>::type
							 | 
						||
| 
								 | 
							
								    get_info() const;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Returns build information about the program.
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// For example, this function can be used to retreive the options used
							 | 
						||
| 
								 | 
							
								    /// to build the program:
							 | 
						||
| 
								 | 
							
								    /// \code
							 | 
						||
| 
								 | 
							
								    /// std::string build_options =
							 | 
						||
| 
								 | 
							
								    ///     program.get_build_info<std::string>(CL_PROGRAM_BUILD_OPTIONS);
							 | 
						||
| 
								 | 
							
								    /// \endcode
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// \see_opencl_ref{clGetProgramInfo}
							 | 
						||
| 
								 | 
							
								    template<class T>
							 | 
						||
| 
								 | 
							
								    T get_build_info(cl_program_build_info info, const device &device) const
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return detail::get_object_info<T>(clGetProgramBuildInfo, m_program, info, device.id());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Builds the program with \p options.
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// If the program fails to compile, this function will throw an
							 | 
						||
| 
								 | 
							
								    /// opencl_error exception.
							 | 
						||
| 
								 | 
							
								    /// \code
							 | 
						||
| 
								 | 
							
								    /// try {
							 | 
						||
| 
								 | 
							
								    ///     // attempt to compile to program
							 | 
						||
| 
								 | 
							
								    ///     program.build();
							 | 
						||
| 
								 | 
							
								    /// }
							 | 
						||
| 
								 | 
							
								    /// catch(boost::compute::opencl_error &e){
							 | 
						||
| 
								 | 
							
								    ///     // program failed to compile, print out the build log
							 | 
						||
| 
								 | 
							
								    ///     std::cout << program.build_log() << std::endl;
							 | 
						||
| 
								 | 
							
								    /// }
							 | 
						||
| 
								 | 
							
								    /// \endcode
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// \see_opencl_ref{clBuildProgram}
							 | 
						||
| 
								 | 
							
								    void build(const std::string &options = std::string())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        const char *options_string = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if(!options.empty()){
							 | 
						||
| 
								 | 
							
								            options_string = options.c_str();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        cl_int ret = clBuildProgram(m_program, 0, 0, options_string, 0, 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        #ifdef BOOST_COMPUTE_DEBUG_KERNEL_COMPILATION
							 | 
						||
| 
								 | 
							
								        if(ret != CL_SUCCESS){
							 | 
						||
| 
								 | 
							
								            // print the error, source code and build log
							 | 
						||
| 
								 | 
							
								            std::cerr << "Boost.Compute: "
							 | 
						||
| 
								 | 
							
								                      << "kernel compilation failed (" << ret << ")\n"
							 | 
						||
| 
								 | 
							
								                      << "--- source ---\n"
							 | 
						||
| 
								 | 
							
								                      << source()
							 | 
						||
| 
								 | 
							
								                      << "\n--- build log ---\n"
							 | 
						||
| 
								 | 
							
								                      << build_log()
							 | 
						||
| 
								 | 
							
								                      << std::endl;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        #endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if(ret != CL_SUCCESS){
							 | 
						||
| 
								 | 
							
								            BOOST_THROW_EXCEPTION(opencl_error(ret));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
							 | 
						||
| 
								 | 
							
								    /// Compiles the program with \p options.
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// \opencl_version_warning{1,2}
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// \see_opencl_ref{clCompileProgram}
							 | 
						||
| 
								 | 
							
								    void compile(const std::string &options = std::string())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        const char *options_string = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if(!options.empty()){
							 | 
						||
| 
								 | 
							
								            options_string = options.c_str();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        cl_int ret = clCompileProgram(
							 | 
						||
| 
								 | 
							
								            m_program, 0, 0, options_string, 0, 0, 0, 0, 0
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if(ret != CL_SUCCESS){
							 | 
						||
| 
								 | 
							
								            BOOST_THROW_EXCEPTION(opencl_error(ret));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Links the programs in \p programs with \p options in \p context.
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// \opencl_version_warning{1,2}
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// \see_opencl_ref{clLinkProgram}
							 | 
						||
| 
								 | 
							
								    static program link(const std::vector<program> &programs,
							 | 
						||
| 
								 | 
							
								                        const context &context,
							 | 
						||
| 
								 | 
							
								                        const std::string &options = std::string())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        const char *options_string = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if(!options.empty()){
							 | 
						||
| 
								 | 
							
								            options_string = options.c_str();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        cl_int ret;
							 | 
						||
| 
								 | 
							
								        cl_program program_ = clLinkProgram(
							 | 
						||
| 
								 | 
							
								            context.get(),
							 | 
						||
| 
								 | 
							
								            0,
							 | 
						||
| 
								 | 
							
								            0,
							 | 
						||
| 
								 | 
							
								            options_string,
							 | 
						||
| 
								 | 
							
								            static_cast<uint_>(programs.size()),
							 | 
						||
| 
								 | 
							
								            reinterpret_cast<const cl_program*>(&programs[0]),
							 | 
						||
| 
								 | 
							
								            0,
							 | 
						||
| 
								 | 
							
								            0,
							 | 
						||
| 
								 | 
							
								            &ret
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if(!program_){
							 | 
						||
| 
								 | 
							
								            BOOST_THROW_EXCEPTION(opencl_error(ret));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return program(program_, false);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    #endif // CL_VERSION_1_2
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Returns the build log.
							 | 
						||
| 
								 | 
							
								    std::string build_log() const
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return get_build_info<std::string>(CL_PROGRAM_BUILD_LOG, get_devices().front());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Creates and returns a new kernel object for \p name.
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// For example, to create the \c "foo" kernel (after the program has been
							 | 
						||
| 
								 | 
							
								    /// created and built):
							 | 
						||
| 
								 | 
							
								    /// \code
							 | 
						||
| 
								 | 
							
								    /// boost::compute::kernel foo_kernel = foo_program.create_kernel("foo");
							 | 
						||
| 
								 | 
							
								    /// \endcode
							 | 
						||
| 
								 | 
							
								    kernel create_kernel(const std::string &name) const;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Returns \c true if the program is the same at \p other.
							 | 
						||
| 
								 | 
							
								    bool operator==(const program &other) const
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return m_program == other.m_program;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Returns \c true if the program is different from \p other.
							 | 
						||
| 
								 | 
							
								    bool operator!=(const program &other) const
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return m_program != other.m_program;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// \internal_
							 | 
						||
| 
								 | 
							
								    operator cl_program() const
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return m_program;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Creates a new program with \p source in \p context.
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// \see_opencl_ref{clCreateProgramWithSource}
							 | 
						||
| 
								 | 
							
								    static program create_with_source(const std::string &source,
							 | 
						||
| 
								 | 
							
								                                      const context &context)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        const char *source_string = source.c_str();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        cl_int error = 0;
							 | 
						||
| 
								 | 
							
								        cl_program program_ = clCreateProgramWithSource(context,
							 | 
						||
| 
								 | 
							
								                                                        uint_(1),
							 | 
						||
| 
								 | 
							
								                                                        &source_string,
							 | 
						||
| 
								 | 
							
								                                                        0,
							 | 
						||
| 
								 | 
							
								                                                        &error);
							 | 
						||
| 
								 | 
							
								        if(!program_){
							 | 
						||
| 
								 | 
							
								            BOOST_THROW_EXCEPTION(opencl_error(error));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return program(program_, false);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Creates a new program with \p sources in \p context.
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// \see_opencl_ref{clCreateProgramWithSource}
							 | 
						||
| 
								 | 
							
								    static program create_with_source(const std::vector<std::string> &sources,
							 | 
						||
| 
								 | 
							
								                                      const context &context)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        std::vector<const char*> source_strings(sources.size());
							 | 
						||
| 
								 | 
							
								        for(size_t i = 0; i < sources.size(); i++){
							 | 
						||
| 
								 | 
							
								            source_strings[i] = sources[i].c_str();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        cl_int error = 0;
							 | 
						||
| 
								 | 
							
								        cl_program program_ = clCreateProgramWithSource(context,
							 | 
						||
| 
								 | 
							
								                                                        uint_(sources.size()),
							 | 
						||
| 
								 | 
							
								                                                        &source_strings[0],
							 | 
						||
| 
								 | 
							
								                                                        0,
							 | 
						||
| 
								 | 
							
								                                                        &error);
							 | 
						||
| 
								 | 
							
								        if(!program_){
							 | 
						||
| 
								 | 
							
								            BOOST_THROW_EXCEPTION(opencl_error(error));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return program(program_, false);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Creates a new program with \p file in \p context.
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// \see_opencl_ref{clCreateProgramWithSource}
							 | 
						||
| 
								 | 
							
								    static program create_with_source_file(const std::string &file,
							 | 
						||
| 
								 | 
							
								                                           const context &context)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        // open file stream
							 | 
						||
| 
								 | 
							
								        std::ifstream stream(file.c_str());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if(stream.fail()){
							 | 
						||
| 
								 | 
							
								          BOOST_THROW_EXCEPTION(std::ios_base::failure("failed to create stream."));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // read source
							 | 
						||
| 
								 | 
							
								        std::string source(
							 | 
						||
| 
								 | 
							
								            (std::istreambuf_iterator<char>(stream)),
							 | 
						||
| 
								 | 
							
								            std::istreambuf_iterator<char>()
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // create program
							 | 
						||
| 
								 | 
							
								        return create_with_source(source, context);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Creates a new program with \p binary of \p binary_size in
							 | 
						||
| 
								 | 
							
								    /// \p context.
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// \see_opencl_ref{clCreateProgramWithBinary}
							 | 
						||
| 
								 | 
							
								    static program create_with_binary(const unsigned char *binary,
							 | 
						||
| 
								 | 
							
								                                      size_t binary_size,
							 | 
						||
| 
								 | 
							
								                                      const context &context)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        const cl_device_id device = context.get_device().id();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        cl_int error = 0;
							 | 
						||
| 
								 | 
							
								        cl_int binary_status = 0;
							 | 
						||
| 
								 | 
							
								        cl_program program_ = clCreateProgramWithBinary(context,
							 | 
						||
| 
								 | 
							
								                                                        uint_(1),
							 | 
						||
| 
								 | 
							
								                                                        &device,
							 | 
						||
| 
								 | 
							
								                                                        &binary_size,
							 | 
						||
| 
								 | 
							
								                                                        &binary,
							 | 
						||
| 
								 | 
							
								                                                        &binary_status,
							 | 
						||
| 
								 | 
							
								                                                        &error);
							 | 
						||
| 
								 | 
							
								        if(!program_){
							 | 
						||
| 
								 | 
							
								            BOOST_THROW_EXCEPTION(opencl_error(error));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if(binary_status != CL_SUCCESS){
							 | 
						||
| 
								 | 
							
								            BOOST_THROW_EXCEPTION(opencl_error(binary_status));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return program(program_, false);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Creates a new program with \p binary in \p context.
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// \see_opencl_ref{clCreateProgramWithBinary}
							 | 
						||
| 
								 | 
							
								    static program create_with_binary(const std::vector<unsigned char> &binary,
							 | 
						||
| 
								 | 
							
								                                      const context &context)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return create_with_binary(&binary[0], binary.size(), context);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Creates a new program with \p file in \p context.
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// \see_opencl_ref{clCreateProgramWithBinary}
							 | 
						||
| 
								 | 
							
								    static program create_with_binary_file(const std::string &file,
							 | 
						||
| 
								 | 
							
								                                           const context &context)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        // open file stream
							 | 
						||
| 
								 | 
							
								        std::ifstream stream(file.c_str(), std::ios::in | std::ios::binary);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // read binary
							 | 
						||
| 
								 | 
							
								        std::vector<unsigned char> binary(
							 | 
						||
| 
								 | 
							
								            (std::istreambuf_iterator<char>(stream)),
							 | 
						||
| 
								 | 
							
								            std::istreambuf_iterator<char>()
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // create program
							 | 
						||
| 
								 | 
							
								        return create_with_binary(&binary[0], binary.size(), context);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
							 | 
						||
| 
								 | 
							
								    /// Creates a new program with the built-in kernels listed in
							 | 
						||
| 
								 | 
							
								    /// \p kernel_names for \p devices in \p context.
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// \opencl_version_warning{1,2}
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// \see_opencl_ref{clCreateProgramWithBuiltInKernels}
							 | 
						||
| 
								 | 
							
								    static program create_with_builtin_kernels(const context &context,
							 | 
						||
| 
								 | 
							
								                                               const std::vector<device> &devices,
							 | 
						||
| 
								 | 
							
								                                               const std::string &kernel_names)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        cl_int error = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        cl_program program_ = clCreateProgramWithBuiltInKernels(
							 | 
						||
| 
								 | 
							
								            context.get(),
							 | 
						||
| 
								 | 
							
								            static_cast<uint_>(devices.size()),
							 | 
						||
| 
								 | 
							
								            reinterpret_cast<const cl_device_id *>(&devices[0]),
							 | 
						||
| 
								 | 
							
								            kernel_names.c_str(),
							 | 
						||
| 
								 | 
							
								            &error
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if(!program_){
							 | 
						||
| 
								 | 
							
								            BOOST_THROW_EXCEPTION(opencl_error(error));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return program(program_, false);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    #endif // CL_VERSION_1_2
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// Create a new program with \p source in \p context and builds it with \p options.
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * In case BOOST_COMPUTE_USE_OFFLINE_CACHE macro is defined,
							 | 
						||
| 
								 | 
							
								     * the compiled binary is stored for reuse in the offline cache located in
							 | 
						||
| 
								 | 
							
								     * $HOME/.boost_compute on UNIX-like systems and in %APPDATA%/boost_compute
							 | 
						||
| 
								 | 
							
								     * on Windows.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    static program build_with_source(
							 | 
						||
| 
								 | 
							
								            const std::string &source,
							 | 
						||
| 
								 | 
							
								            const context     &context,
							 | 
						||
| 
								 | 
							
								            const std::string &options = std::string()
							 | 
						||
| 
								 | 
							
								            )
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								#ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
							 | 
						||
| 
								 | 
							
								        // Get hash string for the kernel.
							 | 
						||
| 
								 | 
							
								        device   d = context.get_device();
							 | 
						||
| 
								 | 
							
								        platform p = d.platform();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        detail::sha1 hash;
							 | 
						||
| 
								 | 
							
								        hash.process( p.name()    )
							 | 
						||
| 
								 | 
							
								            .process( p.version() )
							 | 
						||
| 
								 | 
							
								            .process( d.name()    )
							 | 
						||
| 
								 | 
							
								            .process( options     )
							 | 
						||
| 
								 | 
							
								            .process( source      )
							 | 
						||
| 
								 | 
							
								            ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Try to get cached program binaries:
							 | 
						||
| 
								 | 
							
								        try {
							 | 
						||
| 
								 | 
							
								            boost::optional<program> prog = load_program_binary(hash, context);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (prog) {
							 | 
						||
| 
								 | 
							
								                prog->build(options);
							 | 
						||
| 
								 | 
							
								                return *prog;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        } catch (...) {
							 | 
						||
| 
								 | 
							
								            // Something bad happened. Fallback to normal compilation.
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Cache is apparently not available. Just compile the sources.
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								        const char *source_string = source.c_str();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        cl_int error = 0;
							 | 
						||
| 
								 | 
							
								        cl_program program_ = clCreateProgramWithSource(context,
							 | 
						||
| 
								 | 
							
								                                                        uint_(1),
							 | 
						||
| 
								 | 
							
								                                                        &source_string,
							 | 
						||
| 
								 | 
							
								                                                        0,
							 | 
						||
| 
								 | 
							
								                                                        &error);
							 | 
						||
| 
								 | 
							
								        if(!program_){
							 | 
						||
| 
								 | 
							
								            BOOST_THROW_EXCEPTION(opencl_error(error));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        program prog(program_, false);
							 | 
						||
| 
								 | 
							
								        prog.build(options);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
							 | 
						||
| 
								 | 
							
								        // Save program binaries for future reuse.
							 | 
						||
| 
								 | 
							
								        save_program_binary(hash, prog);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return prog;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								#ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
							 | 
						||
| 
								 | 
							
								    // Saves program binaries for future reuse.
							 | 
						||
| 
								 | 
							
								    static void save_program_binary(const std::string &hash, const program &prog)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        std::string fname = detail::program_binary_path(hash, true) + "kernel";
							 | 
						||
| 
								 | 
							
								        std::ofstream bfile(fname.c_str(), std::ios::binary);
							 | 
						||
| 
								 | 
							
								        if (!bfile) return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        std::vector<unsigned char> binary = prog.binary();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        size_t binary_size = binary.size();
							 | 
						||
| 
								 | 
							
								        bfile.write((char*)&binary_size, sizeof(size_t));
							 | 
						||
| 
								 | 
							
								        bfile.write((char*)binary.data(), binary_size);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Tries to read program binaries from file cache.
							 | 
						||
| 
								 | 
							
								    static boost::optional<program> load_program_binary(
							 | 
						||
| 
								 | 
							
								            const std::string &hash, const context &ctx
							 | 
						||
| 
								 | 
							
								            )
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        std::string fname = detail::program_binary_path(hash) + "kernel";
							 | 
						||
| 
								 | 
							
								        std::ifstream bfile(fname.c_str(), std::ios::binary);
							 | 
						||
| 
								 | 
							
								        if (!bfile) return boost::optional<program>();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        size_t binary_size;
							 | 
						||
| 
								 | 
							
								        std::vector<unsigned char> binary;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        bfile.read((char*)&binary_size, sizeof(size_t));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        binary.resize(binary_size);
							 | 
						||
| 
								 | 
							
								        bfile.read((char*)binary.data(), binary_size);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return boost::optional<program>(
							 | 
						||
| 
								 | 
							
								                program::create_with_binary(
							 | 
						||
| 
								 | 
							
								                    binary.data(), binary_size, ctx
							 | 
						||
| 
								 | 
							
								                    )
							 | 
						||
| 
								 | 
							
								                );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif // BOOST_COMPUTE_USE_OFFLINE_CACHE
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								    cl_program m_program;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/// \internal_ define get_info() specializations for program
							 | 
						||
| 
								 | 
							
								BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(program,
							 | 
						||
| 
								 | 
							
								    ((cl_uint, CL_PROGRAM_REFERENCE_COUNT))
							 | 
						||
| 
								 | 
							
								    ((cl_context, CL_PROGRAM_CONTEXT))
							 | 
						||
| 
								 | 
							
								    ((cl_uint, CL_PROGRAM_NUM_DEVICES))
							 | 
						||
| 
								 | 
							
								    ((std::vector<cl_device_id>, CL_PROGRAM_DEVICES))
							 | 
						||
| 
								 | 
							
								    ((std::string, CL_PROGRAM_SOURCE))
							 | 
						||
| 
								 | 
							
								    ((std::vector<size_t>, CL_PROGRAM_BINARY_SIZES))
							 | 
						||
| 
								 | 
							
								    ((std::vector<unsigned char *>, CL_PROGRAM_BINARIES))
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef CL_VERSION_1_2
							 | 
						||
| 
								 | 
							
								BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(program,
							 | 
						||
| 
								 | 
							
								    ((size_t, CL_PROGRAM_NUM_KERNELS))
							 | 
						||
| 
								 | 
							
								    ((std::string, CL_PROGRAM_KERNEL_NAMES))
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								#endif // CL_VERSION_1_2
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								} // end compute namespace
							 | 
						||
| 
								 | 
							
								} // end boost namespace
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif // BOOST_COMPUTE_PROGRAM_HPP
							 |