Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkOclFilter.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 //Ocl
18 #include "mitkOclFilter.h"
19 #include "mitkOclUtils.h"
20 #include "mitkOpenCLActivator.h"
21 
22 //Mitk
23 #include <mitkLogMacros.h>
24 #include <mitkConfig.h>
25 
26 //usService
27 #include "usServiceReference.h"
28 #include <usServiceRegistration.h>
29 #include <usModuleContext.h>
30 #include <usGetModuleContext.h>
31 #include <usModule.h>
32 #include <usModuleResource.h>
33 #include <usModuleResourceStream.h>
34 
36  : m_ClCompilerFlags(""),
37  m_ClProgram(NULL),
38  m_CommandQue(NULL),
39  m_FilterID("mitkOclFilter"),
40  m_Preambel(" "),
41  m_Initialized(false)
42 {
43 }
44 
46  : m_ClCompilerFlags(""),
47  m_ClProgram(NULL),
48  m_CommandQue(NULL),
49  m_FilterID(filename),
50  m_Preambel(" "),
51  m_Initialized(false)
52 {
53  m_ClFiles.push_back(filename);
54 }
55 
57 {
58  MITK_DEBUG << "OclFilter Destructor";
59 
60  // release program
61  if (m_ClProgram)
62  {
65 
66  // remove program from storage
67  resources->RemoveProgram(m_FilterID);
68  }
69 }
70 
71 bool mitk::OclFilter::ExecuteKernel( cl_kernel kernel, unsigned int workSizeDim )
72 {
73  cl_int clErr = 0;
74 
75  clErr = clEnqueueNDRangeKernel( this->m_CommandQue, kernel, workSizeDim,
76  NULL, this->m_GlobalWorkSize, m_LocalWorkSize, 0, NULL, NULL);
77 
78  CHECK_OCL_ERR( clErr );
79 
80  return ( clErr == CL_SUCCESS );
81 }
82 
83 
85 {
88 
89  m_CommandQue = resources->GetCommandQueue();
90 
91  cl_int clErr = 0;
92  m_Initialized = CHECK_OCL_ERR(clErr);
93 
94  if ( m_ClFiles.empty())
95  {
96  MITK_ERROR<<"No OpenCL Source FILE specified";
97  return false;
98  }
99 
100  if (m_ClProgram == NULL)
101  {
102  try
103  {
104  this->m_ClProgram = resources->GetProgram( this->m_FilterID );
105  }
106  catch(const mitk::Exception& e)
107  {
108  MITK_INFO << "Program not stored in resource manager, compiling.";
109  this->CompileSource();
110  }
111  }
112 
113  return m_Initialized;
114 }
115 
116 void mitk::OclFilter::LoadSourceFiles(CStringList &sourceCode, ClSizeList &sourceCodeSize)
117 {
118  for( CStringList::iterator it = m_ClFiles.begin(); it != m_ClFiles.end(); ++it )
119  {
120  MITK_DEBUG << "Load file :" << *it;
121  us::ModuleResource mdr = GetModule()->GetResource(*it);
122 
123  if( !mdr.IsValid() )
124  MITK_WARN << "Could not load resource: " << mdr.GetName() << " is invalid!";
125 
126  us:ModuleResourceStream rss(mdr);
127 
128  // read resource file to a string
129  std::istreambuf_iterator<char> eos;
130  std::string source(std::istreambuf_iterator<char>(rss), eos);
131 
132  // add preambel and build up string to compile
133  std::string src(m_Preambel);
134  src.append("\n");
135  src.append(source);
136 
137  // allocate new char buffer
138  char* tmp = new char[src.size() + 1];
139  strcpy(tmp,src.c_str());
140 
141  // add source to list
142  sourceCode.push_back((const char*)tmp);
143  sourceCodeSize.push_back(src.size());
144  }
145 }
146 
148 {
149  // helper variable
150  int clErr = 0;
151  CStringList sourceCode;
152  ClSizeList sourceCodeSize;
153 
154  if (m_ClFiles.empty())
155  {
156  MITK_ERROR("ocl.filter") << "No shader source file was set";
157  return;
158  }
159 
160  //get a valid opencl context
163 
164  cl_context gpuContext = resources->GetContext();
165  // load the program source from file
166  LoadSourceFiles(sourceCode, sourceCodeSize);
167 
168  if ( !sourceCode.empty() )
169  {
170  // create program from all files in the file list
171  m_ClProgram = clCreateProgramWithSource(gpuContext, sourceCode.size(), &sourceCode[0], &sourceCodeSize[0], &clErr);
172  CHECK_OCL_ERR(clErr);
173 
174  // build the source code
175  MITK_DEBUG << "Building Program Source";
176  std::string compilerOptions = "";
177  compilerOptions.append(m_ClCompilerFlags);
178 
179  MITK_DEBUG("ocl.filter") << "cl compiler flags: " << compilerOptions.c_str();
180 
181  clErr = clBuildProgram(m_ClProgram, 0, NULL, compilerOptions.c_str(), NULL, NULL);
182  CHECK_OCL_ERR(clErr);
183 
184  // if OpenCL Source build failed
185  if (clErr != CL_SUCCESS)
186  {
187  MITK_ERROR("ocl.filter") << "Failed to build source";
188  oclLogBuildInfo(m_ClProgram, resources->GetCurrentDevice() );
189  oclLogBinary(m_ClProgram, resources->GetCurrentDevice() );
190  m_Initialized = false;
191  }
192 
193  // store the succesfully build program into the program storage provided by the resource service
194  resources->InsertProgram(m_ClProgram, m_FilterID, true);
195 
196  // free the char buffers with the source code
197  for( CStringList::iterator it = sourceCode.begin(); it != sourceCode.end(); ++it )
198  {
199  delete[] *it;
200  }
201  }
202  else
203  {
204  MITK_ERROR("ocl.filter") << "Could not load from source";
205  m_Initialized = false;
206  }
207 }
208 
209 void mitk::OclFilter::SetWorkingSize(unsigned int locx, unsigned int dimx, unsigned int locy, unsigned int dimy, unsigned int locz, unsigned int dimz)
210 {
211  // set the local work size
212  this->m_LocalWorkSize[0] = locx;
213  this->m_LocalWorkSize[1] = locy;
214  this->m_LocalWorkSize[2] = locz;
215 
216  this->m_GlobalWorkSize[0] = dimx;
217  this->m_GlobalWorkSize[1] = dimy;
218  this->m_GlobalWorkSize[2] = dimz;
219 
220  // estimate the global work size
221  this->m_GlobalWorkSize[0] = iDivUp( dimx, this->m_LocalWorkSize[0]) * this->m_LocalWorkSize[0];
222 
223  if ( dimy > 1)
224  this->m_GlobalWorkSize[1] = iDivUp( dimy, this->m_LocalWorkSize[1]) * this->m_LocalWorkSize[1];
225  if( dimz > 1 )
226  this->m_GlobalWorkSize[2] = iDivUp( dimz, this->m_LocalWorkSize[2]) * this->m_LocalWorkSize[2];
227 }
228 
229 void mitk::OclFilter::SetSourcePreambel(const char* preambel)
230 {
231  this->m_Preambel = preambel;
232 }
233 
235 {
236  m_ClFiles.push_back(filename);
237 }
238 
239 void mitk::OclFilter::SetCompilerFlags(const char* flags)
240 {
241  m_ClCompilerFlags = flags;
242 }
243 
244 
246 {
247  return m_Initialized;
248 }
#define CHECK_OCL_ERR(_er)
Definition: mitkOclUtils.h:25
unsigned int iDivUp(unsigned int dividend, unsigned int divisor)
Method to estimate an integer quotient C from given dividend and divisor higher or equal to the corre...
ServiceReferenceU GetServiceReference(const std::string &clazz)
virtual cl_command_queue GetCommandQueue() const =0
Returns a valid cl_command_queue related to the (one) OpenCL context.
OclFilter()
Constructor.
#define MITK_INFO
Definition: mitkLogMacros.h:22
void SetSourcePreambel(const char *preambel)
Add some source code on the beginning of the loaded source.
#define MITK_ERROR
Definition: mitkLogMacros.h:24
std::string GetName() const
bool Initialize()
Initialize all necessary parts of the filter.
#define MITK_DEBUG
Definition: mitkLogMacros.h:26
void oclLogBinary(cl_program clProg, cl_device_id clDev)
Logs the GPU Program binary code.
void CompileSource()
Compile the program source.
virtual bool IsInitialized()
Returns true if the initialization was successfull.
std::vector< const char * > CStringList
Definition: mitkOclFilter.h:66
void * GetService(const ServiceReferenceBase &reference)
virtual ~OclFilter()
Destructor.
#define MITK_WARN
Definition: mitkLogMacros.h:23
An object of this class represents an exception of MITK. Please don't instantiate exceptions manually...
Definition: mitkException.h:49
static const std::string filename
std::vector< vcl_size_t > ClSizeList
Definition: mitkOclFilter.h:67
CStringList m_ClFiles
List of sourcefiles that will be compiled for this filter.
Definition: mitkOclFilter.h:91
void oclLogBuildInfo(cl_program clProg, cl_device_id clDev)
Shows the OpenCL-Program build info, called if clBuildProgram != CL_SUCCES.
virtual void RemoveProgram(const std::string &name)=0
Remove given program from storage.
void SetCompilerFlags(const char *flags)
Set specific compilerflags to compile the CL source. Default is set to NULL; example: "-cl-fast-relax...
virtual cl_context GetContext() const =0
Returns a valid OpenCL Context (if applicable) or NULL if none present.
void SetWorkingSize(unsigned int locx, unsigned int dimx, unsigned int locy=1, unsigned int dimy=1, unsigned int locz=1, unsigned int dimz=1)
Set the working size for the following OpenCL kernel call.
bool ExecuteKernel(cl_kernel kernel, unsigned int workSizeDim)
Execute the given kernel on the OpenCL Index-Space defined by the local and global work sizes...
void LoadSourceFiles(CStringList &SourceCodeList, ClSizeList &SourceCodeSizeList)
Helper functions that load sourcefiles from the module context in the Initialize function.
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
void AddSourceFile(const char *filename)
Add a source file from the resource files to the OpenCL shader file list. Multiple files can be added...
Declaration of the OpenCL Resources micro-service.