Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
clfProgram.cpp
1 /*
2  This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4  Copyright (C) 2003, 2004 (see file CONTACTS for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10  BIAS is free software; you can redistribute it and/or modify
11  it under the terms of the GNU Lesser General Public License as published by
12  the Free Software Foundation; either version 2.1 of the License, or
13  (at your option) any later version.
14 
15  BIAS is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with BIAS; if not, write to the Free Software
22  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23  */
24 
25 #include <Base/Common/BIASpragma.hh>
26 #include <Base/Common/FileHandling.hh>
27 #include <OpenCLFramework/clfProgram.hh>
28 #include <OpenCLFramework/clfException.hh>
29 #include <fstream>
30 #include <iostream>
31 #include <Base/Debug/Error.hh>
32 #include <bias_config.h>
33 
34 using namespace BIAS;
35 using namespace std;
36 
37 clfKernelSources clfProgram::kernelsourcesdb_;
38 std::vector<std::string> clfProgram::additionalsourcedirs_;
39 
40 clfProgram::clfProgram(cl::Context *context, std::vector<cl::Device> *devices) {
41  context_ = context;
42  devices_ = devices;
43  sources_.clear();
44  addWriteMultiplier_ = false;
45 
46  size_t testHeight;
47  string name;
48  (*devices_)[0].getInfo( (cl_device_info)CL_DEVICE_IMAGE2D_MAX_HEIGHT, &testHeight);
49  (*devices_)[0].getInfo( (cl_device_info)CL_DEVICE_NAME, &name);
50  if (testHeight == 16383) {
51  if (name == "GeForce GTX 285") {
52  BIASWARNONCE("you seem to have a gfx card with _image_write_coordinate_ bug (fkellner)");
53  addWriteMultiplier_ = true;
54  }
55  }
56 }
57 
59  for (unsigned i=0;i<sources_.size();i++) {
60  delete[] sources_[i].first;
61  }
62 }
63 
64 std::string clfProgram::AddSource(string filename) {
65  string sourcedb = kernelsourcesdb_.GetSource(filename);
66  if (sourcedb.length()>0) {
67  AddSourceFromString(sourcedb);
68  } else {
69  if (!BIAS::FileHandling::FileExists(filename)) {
70  if (BIAS::FileHandling::FileExists(BIAS_SOURCE_DIR+filename)) {
71  filename = BIAS_SOURCE_DIR+filename;
72  } else {
73  bool found = false;
74  additionalsourcedirs_.push_back("D:\\DeCS\\decs-src\\KEMScan");
75  for (unsigned int i=0;i<additionalsourcedirs_.size();i++) {
76  if (BIAS::FileHandling::FileExists(additionalsourcedirs_[i]+filename)) {
77  filename = additionalsourcedirs_[i]+filename;
78  found = true;
79  break;
80  }
81  }
82  if (!found) {
83  std::string err = "source file could not be found: "+filename;
84  THROW_CL_EXCEPTION(cl::Error(-100, err.c_str()));
85  }
86  }
87  }
88  ifstream sourceFile(filename.c_str());
89  string sourceCode(istreambuf_iterator<char>(sourceFile), (istreambuf_iterator<char>()));
90  if (sourceCode.length() == 0) {
91  std::string err = "source length = 0 for file "+filename;
92  THROW_CL_EXCEPTION(cl::Error(-100, err.c_str()));
93  }
94  sourcedb = sourceCode;
95  AddSourceFromString(sourceCode);
96  }
97  return sourcedb;
98 }
99 
100 void clfProgram::AddSourceFromString(string sourceCode) {
101  if (sourceCode.length() == 0){
102  std::string err = "source length = 0 for source "+sourceCode;
103  THROW_CL_EXCEPTION(cl::Error(-100, err.c_str()));
104  }
105  if (addWriteMultiplier_) {
106  sourceCode = "#define XM 2\n"+sourceCode;
107  } else {
108  sourceCode = "#define XM 1\n"+sourceCode;
109  }
110  char *code = new char[sourceCode.length()];
111  memcpy(code, sourceCode.c_str(), sourceCode.length());
112  sources_.push_back(make_pair(code, sourceCode.length()));
113 }
114 
115 void clfProgram::Build(int deviceNr, std::string options) {
116  program_ = cl::Program(*context_, sources_);
117  cl_int error;
118  try {
119  if (options.length() == 0) {
120  error = program_.build(*devices_);
121  } else {
122  error = program_.build(*devices_, options.c_str());
123  }
124  } catch (cl::Error &err) {
125  string log="";
126  cl_build_status bs = program_.getBuildInfo<CL_PROGRAM_BUILD_STATUS> (
127  (*devices_)[deviceNr]);
128  log+="Build status:\t";
129  switch (bs) {
130  case CL_BUILD_NONE:
131  log+="None\n";
132  break;
133  case CL_BUILD_ERROR:
134  log+="Build error\n";
135  break;
136  case CL_BUILD_SUCCESS:
137  log+="Success\n";
138  break;
139  case CL_BUILD_IN_PROGRESS:
140  log+="Build in progress\n";
141  break;
142  default:
143  log+="ERROR\n";
144  break;
145  }
146 
147  log+="Build log:\t";
148  log+= program_.getBuildInfo<CL_PROGRAM_BUILD_LOG>((*devices_)[deviceNr])+"\n";
149  THROW_CL_EXCEPTION(cl::Error(-100, log.c_str()));
150  }
151 }
152 
153 std::string clfProgram::GetBuildLog(int deviceNr) {
154  return program_.getBuildInfo<CL_PROGRAM_BUILD_LOG>((*devices_)[deviceNr]);
155 }
156 
157 
158 void clfProgram::AddKernel(string kernelname) {
159  try {
160  if (kernels_.find(kernelname) != kernels_.end()) {
161  // already added
162  return;
163  }
164  kernels_.insert(make_pair(kernelname, cl::Kernel(program_, kernelname.c_str() )));
165  } catch (cl::Error &err) {
166  cout<<"Kernelname:"<<kernelname<<endl;
167  THROW_CL_EXCEPTION(err);
168  }
169 }
170 
171 void clfProgram::AddKernels(vector<string> kernelnames) {
172  for (unsigned int i=0;i<kernelnames.size();i++) {
173  AddKernel(kernelnames[i]);
174  }
175 }
176 
177 void clfProgram::KernelSetArgument(string kernelname, unsigned int argnumber, clfBuffer &buffer) {
178  try {
179  kernels_[ kernelname ].setArg( argnumber, buffer.buffer() );
180  } catch (cl::Error &err) {
181  THROW_CL_EXCEPTION(err);
182  }
183 }
184 
185 void clfProgram::KernelSetArgument(string kernelname, unsigned int argnumber, clfImage2D &buffer) {
186  try {
187  kernels_[ kernelname ].setArg( argnumber, buffer.image() );
188  } catch (cl::Error &err) {
189  THROW_CL_EXCEPTION(err);
190  }
191 }
192 
193 #define CLFIMPL_CL_TYPE(type) \
194 void clfProgram::KernelSetArgument(std::string kernelname, unsigned int argnumber, type arg) { \
195  try { \
196  kernels_[ kernelname ].setArg( argnumber, arg ); \
197  } catch (cl::Error &err) { \
198  THROW_CL_EXCEPTION(err); \
199  } \
200 }
201 
202 CLFIMPL_CL_TYPE(cl_float2)
203 CLFIMPL_CL_TYPE(cl_float4)
204 CLFIMPL_CL_TYPE(cl_float8)
205 CLFIMPL_CL_TYPE(cl_float16)
206 
207 CLFIMPL_CL_TYPE(cl_int2)
208 CLFIMPL_CL_TYPE(cl_int4)
209 CLFIMPL_CL_TYPE(cl_int8)
210 CLFIMPL_CL_TYPE(cl_int16)
211 
212 CLFIMPL_CL_TYPE(cl_uint2)
213 CLFIMPL_CL_TYPE(cl_uint4)
214 CLFIMPL_CL_TYPE(cl_uint8)
215 CLFIMPL_CL_TYPE(cl_uint16)
216 
217 void clfProgram::KernelSetArgument(std::string kernelname, unsigned int argnumber, int arg) {
218  try {
219  kernels_[ kernelname ].setArg( argnumber, arg );
220  } catch (cl::Error &err) {
221  THROW_CL_EXCEPTION(err);
222  }
223 }
224 
225 void clfProgram::KernelSetArgument(std::string kernelname, unsigned int argnumber, float arg) {
226  try {
227  kernels_[ kernelname ].setArg( argnumber, arg );
228  } catch (cl::Error &err) {
229  THROW_CL_EXCEPTION(err);
230  }
231 }
232 
233 void clfProgram::
234 KernelSetArgument(std::string kernelname, unsigned int argnumber, float* arg)
235 {
236  try {
237  kernels_[ kernelname ].setArg( argnumber, arg );
238  } catch (cl::Error &err) {
239  THROW_CL_EXCEPTION(err);
240  }
241 }
242 
243 void clfProgram::
244 KernelSetLocalArgument(std::string kernelname, unsigned int argnumber, int size) {
245  try {
246  kernels_[ kernelname ].setArg( argnumber, size, NULL );
247  } catch (cl::Error &err) {
248  THROW_CL_EXCEPTION(err);
249  }
250 }
251 
252 
253 cl::Kernel& clfProgram::operator()(string kernelname) {
254  if (kernels_.find(kernelname) == kernels_.end()) {
255  string err = "can not find kernel of name "+kernelname;
256  THROW_CL_EXCEPTION(cl::Error(-100, err.c_str()));
257  }
258  return kernels_[ kernelname ];
259 }
cl::Buffer & buffer()
Definition: clfBuffer.cpp:113
std::string AddSource(std::string filename)
adds source code from a file
Definition: clfProgram.cpp:64
OpenCL Program wrapper.
Definition: clfProgram.hh:53
virtual ~clfProgram()
Definition: clfProgram.cpp:58
OpenCL Image2D wrapper.
Definition: clfImage2D.hh:46
void KernelSetLocalArgument(std::string kernelname, unsigned int argnumber, int size)
Definition: clfProgram.cpp:244
OpenCL Buffer wrapper.
Definition: clfBuffer.hh:43
void Build(int deviceNr=0, std::string options="")
builds the sources added by AddSource and AddSourceFromString
Definition: clfProgram.cpp:115
void AddSourceFromString(std::string sourceCode)
adds source code from a string
Definition: clfProgram.cpp:100
static bool FileExists(const std::string &file)
Check if the given file exists.
cl::Image2D & image() const
Definition: clfImage2D.cpp:191
void KernelSetArgument(std::string kernelname, unsigned int argnumber, clfBuffer &buffer)
set kernel argument
Definition: clfProgram.cpp:177
std::string GetBuildLog(int deviceNr=0)
Definition: clfProgram.cpp:153
void AddKernel(std::string kernelname)
adds a kernel to the program.
Definition: clfProgram.cpp:158
clfProgram(cl::Context *context, std::vector< cl::Device > *devices)
Definition: clfProgram.cpp:40
cl::Kernel & operator()(std::string kernelname)
Definition: clfProgram.cpp:253
void AddKernels(std::vector< std::string > kernelnames)
adds a vector of kernels to the program.
Definition: clfProgram.cpp:171