IPSDK  4_1_0_2
IPSDK : Image Processing Software Development Kit
ProcessingAlgorithmSrcMacros.h
Go to the documentation of this file.
1 // ProcessingAlgorithmSrcMacros.h:
3 // -------------------------------
4 //
15 
16 #ifndef __IPSDKBASEPROCESSING_PROCESSINGALGORITHMSRCMACROS_H__
17 #define __IPSDKBASEPROCESSING_PROCESSINGALGORITHMSRCMACROS_H__
18 
20 #include <IPSDKBaseProcessing/Algorithm/ProcessingInfo.h>
24 #include <boost/thread/lock_guard.hpp>
25 
26 IPSDK_STATIC_MUTEX(ForcedInstructionSetsMutex);
27 
30 
34 #define IPSDK_IMPLEMENT_PROCESSING_ALGORITHM(libraryName, namespaceSeq, className, \
35  eMsgEnum, version) \
36 const className::FunctionSelector& className::accessFunctionSelector() \
37 { \
38  return retrieveFunctionSelector(); \
39 } \
40 const ipsdk::processor::InstructionSetsIdentifier& className::accessForcedInstructionSets() \
41 { \
42  return retrieveForcedInstructionSets(); \
43 } \
44 void className::forceInstructionSets(const ipsdk::processor::InstructionSetsIdentifier& forcedInstructionSetsId) \
45 { \
46  retrieveForcedInstructionSets() = forcedInstructionSetsId; \
47 } \
48 void className::releaseForcedInstructionSets() \
49 { \
50  retrieveForcedInstructionSets().clear(); \
51 } \
52 const ipsdk::processor::InstructionSetsIdentifier& className::getForcedInstructionSets() const \
53 { \
54  return retrieveForcedInstructionSets(); \
55 } \
56 ipsdk::processor::InstructionSetsIdentifier& className::retrieveForcedInstructionSets() \
57 { \
58  boost::lock_guard<boost::mutex> lock(ForcedInstructionSetsMutex::get()); \
59  static ipsdk::processor::InstructionSetsIdentifier g_forcedInstructionSetsId; \
60  return g_forcedInstructionSetsId; \
61 } \
62 const className::FunctionSelector& className::getFunctionSelector() const \
63 { \
64  return retrieveFunctionSelector(); \
65 } \
66 className::FunctionSelector& className::retrieveFunctionSelector() \
67 { \
68  static className::FunctionSelector g_functionSelector; \
69  return g_functionSelector; \
70 } \
71 IPSDK_IMPLEMENT_PROCESSOR(libraryName, namespaceSeq, className, eMsgEnum, version)
72 
75 
78 #define IPSDK_START_ALGORITHM_FUNCTIONS_REGISTRATION(className) \
79  static bool details::functionRegistration() { \
80  typedef className CurProcessorType; \
81  className::DataTypeIdColl dataTypeIdColl; \
82  ipsdk::processor::InstructionSetsIdentifier instructionSetsIdentifier; \
83  className::FunctionType functionPtr; \
84  (functionPtr); \
85  className::FunctionId functionId; \
86  ipsdk::BoolResult bRegistred; \
87  std::string errorMsgColl; \
88  className::FunctionSelector& functionSelector = className::retrieveFunctionSelector();
89 
93 #define IPSDK_REGISTER_GENERIC_ALGORITHM_FUNCTION(dataTypeSeq, isSeq, \
94  functionEfficiency, functionName) \
95  { \
96  BOOST_STATIC_ASSERT_MSG(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE((_)dataTypeSeq)) == \
97  CurProcessorType::g_nbTypesForFunSelection, \
98  "Invalid number of data type in sequence for function selection"); \
99  instructionSetsIdentifier.init(BOOST_PP_ENUM(BOOST_PP_SEQ_SIZE(isSeq), \
100  IPSDK_ENUM_INSTRUCTION_SET_MACRO, isSeq)); \
101  if (functionSelector.isSupported(instructionSetsIdentifier) == true) { \
102  functionPtr = static_cast<CurProcessorType::FunctionType>( \
103  &CurProcessorType::functionName< \
104  BOOST_PP_ENUM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE((_)dataTypeSeq)), \
105  IPSDK_ENUM_IDENTIFIER_VALUE_MACRO, dataTypeSeq) \
106  BOOST_PP_COMMA_IF(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE((_)dataTypeSeq))) \
107  BOOST_PP_ENUM(BOOST_PP_SEQ_SIZE(isSeq), IPSDK_ENUM_INSTRUCTION_SET_MACRO, isSeq) \
108  >); \
109  BOOST_PP_SEQ_FOR_EACH_I(IPSDK_INIT_IDENTIFIER_FROM_VALUE_MACRO, \
110  _, ((_)(_))dataTypeSeq); \
111  IPSDK_REGISTER_ALGORITHM_FUNCTION_MACRO(CurProcessorType, dataTypeSeq, \
112  instructionSetsIdentifier, functionEfficiency) \
113  } \
114  }
115 
119 #define IPSDK_REGISTER_SPECIFIC_ALGORITHM_FUNCTION(dataTypeSeq, isSeq, \
120  functionEfficiency, functionName) \
121  { \
122  BOOST_STATIC_ASSERT_MSG(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE((_)dataTypeSeq)) == \
123  CurProcessorType::g_nbTypesForFunSelection, \
124  "Invalid number of data type in sequence for function selection"); \
125  instructionSetsIdentifier.init(BOOST_PP_ENUM(BOOST_PP_SEQ_SIZE(isSeq), \
126  IPSDK_ENUM_INSTRUCTION_SET_MACRO, isSeq)); \
127  if (functionSelector.isSupported(instructionSetsIdentifier) == true) { \
128  functionPtr = static_cast<CurProcessorType::FunctionType>(&CurProcessorType:: \
129  BOOST_PP_EXPAND functionName); \
130  BOOST_PP_SEQ_FOR_EACH_I(IPSDK_INIT_IDENTIFIER_FROM_VALUE_MACRO, \
131  _, ((_)(_))dataTypeSeq); \
132  IPSDK_REGISTER_ALGORITHM_FUNCTION_MACRO(CurProcessorType, dataTypeSeq, \
133  instructionSetsIdentifier, functionEfficiency) \
134  } \
135  }
136 
139 #define IPSDK_END_ALGORITHM_FUNCTIONS_REGISTRATION() \
140  if (errorMsgColl.size() != 0) { \
141  IPSDKBASEPROCESSING_LOG_TRACE( \
142  [ipsdk::processor::eAlgorithmFunctionMessage::eFunctionRegistrationFailed] % \
143  errorMsgColl); \
144  } \
145  return true; \
146  } \
147  static bool details::safeFunctionRegistration() { \
148  if ((ipsdk::eInstructionSet::COMPIL_IS_TYPE1 == ipsdk::eInstructionSet::eIS_Standard || \
149  ipsdk::core::isAvailable(ipsdk::eInstructionSet::COMPIL_IS_TYPE1) == true) && \
150  (ipsdk::eInstructionSet::COMPIL_IS_TYPE2 == ipsdk::eInstructionSet::eIS_Standard || \
151  ipsdk::core::isAvailable(ipsdk::eInstructionSet::COMPIL_IS_TYPE2) == true) && \
152  (ipsdk::eInstructionSet::COMPIL_IS_TYPE3 == ipsdk::eInstructionSet::eIS_Standard || \
153  ipsdk::core::isAvailable(ipsdk::eInstructionSet::COMPIL_IS_TYPE3) == true)) \
154  return details::functionRegistration(); \
155  else \
156  return false; \
157  } \
158  static bool g_bAlgorithmFunctionsRegistred = details::safeFunctionRegistration();
159 
163 #define IPSDK_IMPLEMENT_GPU_PROCESSING_ALGORITHM(libraryName, namespaceSeq, className, \
164  eMsgEnum, version) \
165 const className::FunctionSelector& className::accessFunctionSelector() \
166 { \
167  return retrieveFunctionSelector(); \
168 } \
169 const className::FunctionSelector& className::getFunctionSelector() const \
170 { \
171  return retrieveFunctionSelector(); \
172 } \
173 className::FunctionSelector& className::retrieveFunctionSelector() \
174 { \
175  static className::FunctionSelector g_functionSelector; \
176  return g_functionSelector; \
177 } \
178 IPSDK_IMPLEMENT_PROCESSOR(libraryName, namespaceSeq, className, eMsgEnum, version)
179 
180 // Create a sequence with 1 item that convert the datatype enumeration value
181 // into the actual buffer type thanks to the call of ipsdk::image::ImageType2Buffer<>::type
182 #define IPSDKCUDA_GET_IDENTIFIER_SEQ_VALUE_IBT(r, data, value) \
183 (ipsdk::image::ImageType2Buffer<ipsdk::image::eImageBufferType::value>::type)
184 
185 // For a given type sequence, assign the templated generic kernel launcher function to function pointer
186 #define IPSDKCUDA_CAST_FCT_PTR(ST) \
187 functionPtr = static_cast<CudaFunctionSelector::FunctionType>( \
188  &CurProcessorType::genericKernelLauncher< \
189  BOOST_PP_SEQ_ENUM( \
190  BOOST_PP_SEQ_FOR_EACH(IPSDKCUDA_GET_IDENTIFIER_SEQ_VALUE_IBT, _, ST))>);
191 
192 // Register a specific templated function
193 #define IPSDKCUDA_REGISTER_FUNCTION(r, product) \
194  IPSDKCUDA_CAST_FCT_PTR(product) \
195  ISPDKCUDA_INIT_IDENTIFIERS(product); \
196  dataTypeIdColl.init(BOOST_PP_ENUM(BOOST_PP_SEQ_SIZE(product), \
197  IPSDK_ENUM_DATATYPE_IDENTIFIER_MACRO, _)); \
198  functionId.init(dataTypeIdColl, functionPtr); \
199  bRegistred = functionSelector.registerFunction(functionId); \
200  if (bRegistred == false) \
201  errorMsgColl += bRegistred.getMsg() + "\n";
202 
203 // Register the generic functions for all type combination
204 #define IPSDKCUDA_REGISTER_GENERIC_GPU_ALGORITHM_FUNCTION(ST) \
205  ISPDKCUDA_DECLARE_IDENTIFIERS(BOOST_PP_SEQ_ELEM(0, ST)); \
206  BOOST_PP_SEQ_FOR_EACH_PRODUCT(IPSDKCUDA_REGISTER_FUNCTION, ST)
207 
208 // Register the no typed function
209 #define IPSDKCUDA_REGISTER_NOTYPE_GPU_ALGORITHM_FUNCTION() \
210  functionPtr = static_cast<CudaFunctionSelector::FunctionType>(&CurProcessorType::genericKernelLauncher);\
211  dataTypeIdColl.init(); \
212  functionId.init(dataTypeIdColl, functionPtr); \
213  bRegistred = functionSelector.registerFunction(functionId); \
214  if (bRegistred == false) \
215  errorMsgColl += bRegistred.getMsg() + "\n";
216 
217 // Begins the function used to register the templated generic functions
218 // used to call a cuda kernel
219 #define IPSDKCUDA_START_GPU_FUNCTIONS_REGISTRATION(AlgoName) \
220 bool details::functionRegistration() \
221 { \
222  typedef AlgoName CurProcessorType; \
223  ipsdk::processor::DataTypeIdentifierColl dataTypeIdColl; \
224  typedef CudaFunctionSelector::FunctionType FunctionType; \
225  FunctionType functionPtr; \
226  (functionPtr); \
227  CudaFunctionSelector::FunctionId functionId; \
228  ipsdk::BoolResult bRegistred; \
229  std::string errorMsgColl; \
230  CudaFunctionSelector& functionSelector = \
231  CurProcessorType::retrieveFunctionSelector();
232 
233 // Ends the function used to register the templated generic functions
234 // used to call a cuda kernel
235 #define IPSDKCUDA_END_GPU_FUNCTIONS_REGISTRATION() \
236  if (errorMsgColl.size() != 0) { \
237  IPSDKBASEPROCESSING_LOG_TRACE( \
238  [ipsdk::processor::eAlgorithmFunctionMessage::eFunctionRegistrationFailed] % \
239  errorMsgColl); \
240  } \
241  return true; \
242  } \
243 static bool g_bAlgorithmFunctionsRegistred = details::functionRegistration();
244 
247 // by adding the prefix "img"
248 // For instance, IPSDKCUDA_GENERATE_GPU_IMAGE_NAME(_pInSubGpuImg) yields img_pInSubGpuImg
249 #define IPSDKCUDA_GENERATE_GPU_IMAGE_NAME(ImgName)\
250 BOOST_PP_CAT(img, ImgName)
251 
256 #define IPSDKCUDA_GENERATE_IMAGE_BUFFER_NAME(ImgName)\
257 BOOST_PP_CAT(IPSDKCUDA_GENERATE_GPU_IMAGE_NAME(ImgName), Buf)
258 
263 #define IPSDKCUDA_GENERATE_IMAGE_BUFFER_NAME_COLL(imgName)\
264 BOOST_PP_CAT(p, IPSDKCUDA_GENERATE_IMAGE_BUFFER_NAME(imgName))
265 
275 #define IPSDKCUDA_EXTRACT_DATA_FROM_IMAGE_MACRO(r, data, elem) \
276 BOOST_PP_TUPLE_ELEM(0, elem) CudaImage& IPSDKCUDA_GENERATE_GPU_IMAGE_NAME(BOOST_PP_TUPLE_ELEM(2, elem)) = \
277  static_cast<BOOST_PP_TUPLE_ELEM(0, elem) CudaImage&>(BOOST_PP_TUPLE_ELEM(2, elem)->getImage()); \
278 BOOST_PP_TUPLE_ELEM(0, elem) BOOST_PP_TUPLE_ELEM(1, elem)** \
279  IPSDKCUDA_GENERATE_IMAGE_BUFFER_NAME_COLL(BOOST_PP_TUPLE_ELEM(2, elem)) = \
280  ipsdk::image::tools::extractBufferDataCollToGpu<BOOST_PP_TUPLE_ELEM(1, elem)>( \
281  IPSDKCUDA_GENERATE_GPU_IMAGE_NAME(BOOST_PP_TUPLE_ELEM(2, elem)));
282 
286 #define IPSDKCUDA_EXTRACT_DATA_FROM_IMAGES(SI) \
287 BOOST_PP_SEQ_FOR_EACH(IPSDKCUDA_EXTRACT_DATA_FROM_IMAGE_MACRO, _, SI) \
288 const unsigned long sizeX = static_cast<unsigned long>(IPSDKCUDA_GENERATE_GPU_IMAGE_NAME(BOOST_PP_TUPLE_ELEM(2, BOOST_PP_SEQ_ELEM(0, SI))).getSizeX()); \
289 const unsigned long sizeY = static_cast<unsigned long>(IPSDKCUDA_GENERATE_GPU_IMAGE_NAME(BOOST_PP_TUPLE_ELEM(2, BOOST_PP_SEQ_ELEM(0, SI))).getSizeY()); \
290 const unsigned long sizeZ = static_cast<unsigned long>(IPSDKCUDA_GENERATE_GPU_IMAGE_NAME(BOOST_PP_TUPLE_ELEM(2, BOOST_PP_SEQ_ELEM(0, SI))).getSizeZ()); \
291 const unsigned long sizeC = static_cast<unsigned long>(IPSDKCUDA_GENERATE_GPU_IMAGE_NAME(BOOST_PP_TUPLE_ELEM(2, BOOST_PP_SEQ_ELEM(0, SI))).getSizeC()); \
292 const unsigned long sizeT = static_cast<unsigned long>(IPSDKCUDA_GENERATE_GPU_IMAGE_NAME(BOOST_PP_TUPLE_ELEM(2, BOOST_PP_SEQ_ELEM(0, SI))).getSizeT()); \
293 ipsdk::gpu::LauncherInfo launcherInfo; \
294 launcherInfo._bInSituProcess = false; \
295 launcherInfo._imgSizeInfo._sizeX = sizeX; \
296 launcherInfo._imgSizeInfo._sizeY = sizeY; \
297 launcherInfo._imgSizeInfo._sizeZ = sizeZ; \
298 launcherInfo._imgSizeInfo._sizeC = sizeC; \
299 launcherInfo._imgSizeInfo._sizeT = sizeT;
300 
301 
302 
306 #define IPSDKCUDA_CHECK_INSITU(pImageAttr1, pImageAttr2) \
307 launcherInfo._bInSituProcess = pImageAttr1->getImage().containSameData(pImageAttr2->getImage())
308 
312 #define IPSDKCUDA_GET_BLOCK_SIZE_2D \
313 ipsdk::hard::GpuDescription& gpuDescription = ipsdk::core::ComputerInfoPool::getInstance().getLocalComputerInfo().getComputerDescription().getGpuDescription(); \
314 launcherInfo._blockSize = gpuDescription.getBlockSize2d(static_cast<int>(_deviceIdx)); \
315 launcherInfo._nbMultiProcessors = gpuDescription.getNbMultiProcessors(static_cast<int>(_deviceIdx)); \
316 launcherInfo._nbThreadsPerMP = gpuDescription.getMaxThreadsPerMultiProcessor(static_cast<int>(_deviceIdx)); \
317 launcherInfo._nbThreadsPerBlock = gpuDescription.getMaxThreadsPerBlock(static_cast<int>(_deviceIdx));
318 
321 #define IPSDKCUDA_GET_BLOCK_SIZE_3D \
322 ipsdk::hard::GpuDescription& gpuDescription = ipsdk::core::ComputerInfoPool::getInstance().getLocalComputerInfo().getComputerDescription().getGpuDescription(); \
323 launcherInfo._blockSize = gpuDescription.getBlockSize3d(static_cast<int>(_deviceIdx)); \
324 launcherInfo._nbMultiProcessors = gpuDescription.getNbMultiProcessors(static_cast<int>(_deviceIdx)); \
325 launcherInfo._nbThreadsPerMP = gpuDescription.getMaxThreadsPerMultiProcessor(static_cast<int>(_deviceIdx)); \
326 launcherInfo._nbThreadsPerBlock = gpuDescription.getMaxThreadsPerBlock(static_cast<int>(_deviceIdx));
327 
332 #define IPSDKCUDA_FREE_BUFFER_DATA_MACRO(r, data, elem)\
333 ipsdk::image::tools::freeBufferDataColl(IPSDKCUDA_GENERATE_IMAGE_BUFFER_NAME_COLL(elem));
334 
337 #define IPSDKCUDA_FREE_BUFFER_DATA_COLL(SI)\
338 BOOST_PP_SEQ_FOR_EACH(IPSDKCUDA_FREE_BUFFER_DATA_MACRO, _, SI)
339 
347 #define IPSDKCUDA_LAUNCH_KERNEL(AlgoName, SeqArg) \
348 ipsdk::gpu::CudaResult res = BOOST_PP_CAT(AlgoName, _knlLauncher)(&launcherInfo, BOOST_PP_SEQ_ENUM(SeqArg));\
349 if(!res._bResult) return BoolResult(false, res._msg);
350 
357 #define IPSDKCUDA_LAUNCH_KERNEL_WITH_FILTERING_INFO(AlgoName, TIn, SeqArg) \
358 ipsdk::gpu::CudaResult res = BOOST_PP_CAT(AlgoName, _knlLauncher)(&launcherInfo, &knlInfo, \
359  _borderPolicyValue, \
360  static_cast<TIn>(_outOfImageValue), \
361  BOOST_PP_SEQ_ENUM(SeqArg)); \
362 if(!res._bResult) return BoolResult(false, res._msg);
363 
370 #define IPSDKCUDA_LAUNCH_KERNEL_WITH_SE_INFO(AlgoName, T, SeqArg) \
371 ipsdk::gpu::CudaResult res = BOOST_PP_CAT(AlgoName, _knlLauncher)(&launcherInfo, &seInfo, \
372  _borderPolicyValue, \
373  static_cast<T>(_outOfImageValue), \
374  BOOST_PP_SEQ_ENUM(SeqArg)); \
375 if(!res._bResult) return BoolResult(false, res._msg);
376 
380 #define IPSDKCUDA_EXTRACT_FILTERING_INFO_2D(pInKnlXY, vOffsetsX, vOffsetsY, vCoefs) \
381  struct ipsdk::gpu::FilteringKernelInfo<float> knlInfo; \
382  knlInfo._nbData = static_cast<unsigned int>(vCoefs.size()); \
383  knlInfo._paddingX = pInKnlXY->getKernel().getSizeX() / 2; \
384  knlInfo._paddingY = pInKnlXY->getKernel().getSizeY() / 2; \
385  knlInfo._pOffsetsX = vOffsetsX.data(); \
386  knlInfo._pOffsetsY = vOffsetsY.data(); \
387  knlInfo._pCoefs = vCoefs.data();
388 
392 #define IPSDKCUDA_EXTRACT_FILTERING_INFO_3D(pInKnlXYZ, vOffsetsX, vOffsetsY, vOffsetsZ, vCoefs) \
393  struct ipsdk::gpu::FilteringKernelInfo<float> knlInfo; \
394  knlInfo._nbData = static_cast<unsigned int>(vCoefs.size()); \
395  knlInfo._paddingX = pInKnlXYZ->getKernel().getSizeX() / 2; \
396  knlInfo._paddingY = pInKnlXYZ->getKernel().getSizeY() / 2; \
397  knlInfo._paddingZ = pInKnlXYZ->getKernel().getSizeZ() / 2; \
398  knlInfo._pOffsetsX = vOffsetsX.data(); \
399  knlInfo._pOffsetsY = vOffsetsY.data(); \
400  knlInfo._pOffsetsZ = vOffsetsZ.data(); \
401  knlInfo._pCoefs = vCoefs.data();
402 
406 #define IPSDKCUDA_EXTRACT_SE_INFO_2D(pInSEXY, vOffsetsX, vOffsetsY) \
407  struct ipsdk::gpu::StructuringElementInfo seInfo; \
408  seInfo._nbData = static_cast<unsigned int>(vOffsetsX.size()); \
409  seInfo._paddingX = pInSEXY->getStructuringElement().getSizeX() / 2; \
410  seInfo._paddingY = pInSEXY->getStructuringElement().getSizeY() / 2; \
411  seInfo._pOffsetsX = vOffsetsX.data(); \
412  seInfo._pOffsetsY = vOffsetsY.data();
413 
417 #define IPSDKCUDA_EXTRACT_SE_INFO_3D(pInSEXYZ, vOffsetsX, vOffsetsY, vOffsetsZ) \
418  struct ipsdk::gpu::StructuringElementInfo seInfo; \
419  seInfo._nbData = static_cast<unsigned int>(vOffsetsX.size()); \
420  seInfo._paddingX = pInSEXYZ->getStructuringElement().getSizeX() / 2; \
421  seInfo._paddingY = pInSEXYZ->getStructuringElement().getSizeY() / 2; \
422  seInfo._paddingZ = pInSEXYZ->getStructuringElement().getSizeZ() / 2; \
423  seInfo._pOffsetsX = vOffsetsX.data(); \
424  seInfo._pOffsetsY = vOffsetsY.data(); \
425  seInfo._pOffsetsZ = vOffsetsZ.data();
426 
429 
430 #endif // __IPSDKBASEPROCESSING_PROCESSINGALGORITHMSRCMACROS_H__
Predefined base collection types for library.
Internal source part of macros set for processing algorithm class implementation. ...
Utility functions for local computer informations management.
Macros allowing to define a getter to a static mutex.
#define IPSDK_STATIC_MUTEX(MutexName)
macro allowing to create a static mutex
Definition: MutexMacros.h:27