Voxel
 All Classes Namespaces Files Functions Typedefs Enumerations Enumerator Macros Pages
opencl_program.cpp
Go to the documentation of this file.
1 /**
2  \file
3  \brief Contains OpenCL::Program methods.
4 */
5 
6 
7 
8 
9 #include "settings.h"
10 
11 
12 
13 
14 #if ( SETTING_OPENCL != 0 )
15 
16 
17 
18 
19 #include "opencl_program.h"
20 #include "exception.h"
21 #include "opencl_exception.h"
22 #include "helpers.h"
23 
24 #include <boost/iostreams/device/mapped_file.hpp>
25 
26 #include <vector>
27 #include <string>
28 #include <fstream>
29 
30 
31 
32 
33 namespace OpenCL {
34 
35 
36 
37 
38 /*==============================================================================
39  Program methods
40 ==============================================================================*/
41 
42 
44  std::shared_ptr< State > const& pState,
45  char const* const* const filenames,
46  char const* const options,
47  char const* const logFilename
48 ) :
49  m_pState( pState )
50 {
51  cl_int result = CL_SUCCESS;
52  cl_device_id const deviceID = m_pState->DeviceID();
53 
54  // mmap the source code files
55  std::vector< boost::iostreams::mapped_file_source > fileMaps;
56  std::vector< boost::iostreams::mapped_file_source::size_type > fileLengths;
57  std::vector< char const* > fileContents;
58  for ( unsigned int ii = 0; filenames[ ii ] != NULL; ++ii ) {
59 
60  fileMaps.push_back( boost::iostreams::mapped_file_source( filenames[ ii ] ) );
61  if ( ! fileMaps.back().is_open() )
62  THROW_EXCEPTION( "boost::iostreams::mapped_file_source constructor failed!" );
63  fileLengths.push_back( fileMaps.back().size() );
64  fileContents.push_back( fileMaps.back().data() );
65  }
66  assert( fileMaps.size() == fileLengths.size() );
67  assert( fileMaps.size() == fileContents.size() );
68 
69  // make a cl_program from the source
70  m_program.reset( clCreateProgramWithSource( m_pState->Context(), fileMaps.size(), fileContents.data(), fileLengths.data(), &result ) );
71  if ( result != CL_SUCCESS )
72  THROW_OPENCL_EXCEPTION( "clCreateProgramWithSource failed!", result );
73 
74  // try to compile the program
75  result = clBuildProgram( m_program.get(), 1, &deviceID, options, NULL, NULL );
76  if ( logFilename != NULL ) {
77 
78  cl_build_status status = CL_BUILD_NONE;
79  cl_int const statusResult = clGetProgramBuildInfo( m_program.get(), deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL );
80 
81  size_t optionsLength = 0;
82  std::unique_ptr< char[] > options;
83  cl_int optionsResult = clGetProgramBuildInfo( m_program.get(), deviceID, CL_PROGRAM_BUILD_OPTIONS, 0, NULL, &optionsLength );
84  if ( ( optionsResult == CL_SUCCESS ) && ( optionsLength > 1 ) ) {
85 
86  options.reset( new char[ optionsLength ] );
87  optionsResult = clGetProgramBuildInfo( m_program.get(), deviceID, CL_PROGRAM_BUILD_OPTIONS, optionsLength, options.get(), &optionsLength );
88  if ( ( optionsResult == CL_SUCCESS ) && ( optionsLength > 1 ) ) {
89 
90  bool printable = false;
91  for ( unsigned int ii = 0; ( ! printable ) && ( ii < optionsLength ); ++ii )
92  printable |= ( std::isprint( options[ ii ] ) != 0 );
93  if ( ! printable ) {
94 
95  options[ 0 ] = '\0';
96  optionsLength = 1;
97  }
98  }
99  }
100 
101  size_t logLength = 0;
102  std::unique_ptr< char[] > log;
103  cl_int logResult = clGetProgramBuildInfo( m_program.get(), deviceID, CL_PROGRAM_BUILD_LOG, 0, NULL, &logLength );
104  if ( ( logResult == CL_SUCCESS ) && ( logLength > 1 ) ) {
105 
106  log.reset( new char[ logLength ] );
107  logResult = clGetProgramBuildInfo( m_program.get(), deviceID, CL_PROGRAM_BUILD_LOG, logLength, log.get(), &logLength );
108  if ( ( logResult == CL_SUCCESS ) && ( logLength > 1 ) ) {
109 
110  bool printable = false;
111  for ( unsigned int ii = 0; ( ! printable ) && ( ii < logLength ); ++ii )
112  printable |= ( std::isprint( log[ ii ] ) != 0 );
113  if ( ! printable ) {
114 
115  log[ 0 ] = '\0';
116  logLength = 1;
117  }
118  }
119  }
120 
121  if ( ( ( statusResult == CL_SUCCESS ) && ( status != CL_BUILD_SUCCESS ) ) || ( ( logResult == CL_SUCCESS ) && ( logLength > 1 ) ) ) {
122 
123  std::ofstream logFile( logFilename, std::ios_base::out | std::ios_base::trunc );
124  if ( ! logFile.is_open() )
125  THROW_EXCEPTION( "std::ofstream constructor failed!" );
126 
127  bool printed = false;
128  if ( statusResult == CL_SUCCESS ) {
129 
130  char const* message = "<unknown status>";
131  switch( status ) {
132  case CL_BUILD_NONE: { message = "CL_BUILD_NONE"; break; }
133  case CL_BUILD_ERROR: { message = "CL_BUILD_ERROR"; break; }
134  case CL_BUILD_SUCCESS: { message = "CL_BUILD_SUCCESS"; break; }
135  case CL_BUILD_IN_PROGRESS: { message = "CL_BUILD_IN_PROGRESS"; break; }
136  }
137  logFile << "Build status = " << message << " (code=" << status << ')' << std::endl;
138  printed = true;
139  }
140  if ( ( optionsResult == CL_SUCCESS ) && ( optionsLength > 1 ) ) {
141 
142  logFile << "Build options = \"" << CollapseWhitespace( options.get() ) << '"' << std::endl;
143  printed = true;
144  }
145  if ( ( logResult == CL_SUCCESS ) && ( logLength > 1 ) ) {
146 
147  if ( printed )
148  logFile << std::endl << std::endl;
149 
150  logFile <<
151  "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-" << std::endl <<
152  " Build log" << std::endl <<
153  "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-" << std::endl <<
154  std::endl;
155 
156  // strip whitespace
157  int ii = 0;
158  int iiEnd = logLength - 1;
159  for ( ; ( ii < iiEnd ) && ( ! std::isprint( log[ ii ] ) ); ++ii );
160  for ( ; ( iiEnd > ii ) && ( ! std::isprint( log[ iiEnd ] ) ); --iiEnd );
161  logFile.write( log.get() + ii, 1 + iiEnd - ii );
162 
163  logFile << std::endl;
164  printed = true;
165  }
166  for ( unsigned int ii = 0; ii < fileMaps.size(); ++ii ) {
167 
168  if ( printed )
169  logFile << std::endl << std::endl;
170 
171  logFile <<
172  "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-" << std::endl <<
173  " Source code - \"" << filenames[ ii ] << '"' << std::endl <<
174  "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-" << std::endl <<
175  std::endl;
176 
177  // strip whitespace
178  int jj = 0;
179  int jjEnd = fileLengths[ ii ];
180  for ( ; ( jj < jjEnd ) && ( ! std::isprint( fileContents[ ii ][ jj ] ) ); ++jj );
181  for ( ; ( jjEnd > jj ) && ( ! std::isprint( fileContents[ ii ][ jjEnd ] ) ); --jjEnd );
182  logFile.write( fileContents[ ii ] + jj, 1 + jjEnd - jj );
183 
184  logFile << std::endl;
185  printed = true;
186  }
187  }
188  }
189  if ( result != CL_SUCCESS )
190  THROW_OPENCL_EXCEPTION( "clBuildProgram failed!", result );
191 }
192 
193 
194 
195 
196 } // namespace OpenCL
197 
198 
199 
200 
201 #endif // SETTING_OPENCL