diff --git a/modules/core/include/opencv2/core/types_c.h b/modules/core/include/opencv2/core/types_c.h index e0860fff9..192e7f42b 100644 --- a/modules/core/include/opencv2/core/types_c.h +++ b/modules/core/include/opencv2/core/types_c.h @@ -247,7 +247,8 @@ enum { CV_StsAssert= -215, /* assertion failed */ CV_GpuNotSupported= -216, CV_GpuApiCallError= -217, - CV_GpuNppCallError= -218 + CV_GpuNppCallError= -218, + CV_GpuCufftCallError= -219 }; /****************************************************************************************\ diff --git a/modules/gpu/src/cuda/safe_call.hpp b/modules/gpu/src/cuda/safe_call.hpp index b92ab4b0a..e3e00beaa 100644 --- a/modules/gpu/src/cuda/safe_call.hpp +++ b/modules/gpu/src/cuda/safe_call.hpp @@ -44,13 +44,16 @@ #define __OPENCV_CUDA_SAFE_CALL_HPP__ #include "cuda_runtime_api.h" +#include "cufft.h" //#include #if defined(__GNUC__) #define cudaSafeCall(expr) ___cudaSafeCall(expr, __FILE__, __LINE__, __func__) + #define cufftSafeCall(expr) ___cufftSafeCall(expr, __FILE__, __LINE__, __func__) #define nppSafeCall(expr) ___nppSafeCall(expr, __FILE__, __LINE__, __func__) #else /* defined(__CUDACC__) || defined(__MSVC__) */ #define cudaSafeCall(expr) ___cudaSafeCall(expr, __FILE__, __LINE__) + #define cufftSafeCall(expr) ___cufftSafeCall(expr, __FILE__, __LINE__) #define nppSafeCall(expr) ___nppSafeCall(expr, __FILE__, __LINE__) #endif @@ -58,15 +61,22 @@ namespace cv { namespace gpu { - void error( const char *error_string, const char *file, const int line, const char *func = ""); - void nppError( int error, const char *file, const int line, const char *func = ""); + void error(const char *error_string, const char *file, const int line, const char *func = ""); + void nppError(int err, const char *file, const int line, const char *func = ""); + void cufftError(int err, const char *file, const int line, const char *func = ""); static inline void ___cudaSafeCall(cudaError_t err, const char *file, const int line, const char *func = "") { - if( cudaSuccess != err) + if (cudaSuccess != err) cv::gpu::error(cudaGetErrorString(err), file, line, func); } + static inline void ___cufftSafeCall(cufftResult_t err, const char *file, const int line, const char *func = "") + { + if (CUFFT_SUCCESS != err) + cv::gpu::cufftError(err, file, line, func); + } + static inline void ___nppSafeCall(int err, const char *file, const int line, const char *func = "") { if (err < 0) diff --git a/modules/gpu/src/error.cpp b/modules/gpu/src/error.cpp index df4bc17a8..0ca918d52 100644 --- a/modules/gpu/src/error.cpp +++ b/modules/gpu/src/error.cpp @@ -56,6 +56,9 @@ namespace { #define error_entry(entry) { entry, #entry } + ////////////////////////////////////////////////////////////////////////// + // NPP errors + struct NppError { int error; @@ -116,6 +119,40 @@ namespace bool operator()(const NppError& e) const { return e.error == err; } }; + ////////////////////////////////////////////////////////////////////////// + // CUFFT errors + + struct CufftError + { + int code; + string message; + }; + + const CufftError cufft_errors[] = + { + error_entry(CUFFT_INVALID_PLAN), + error_entry(CUFFT_ALLOC_FAILED), + error_entry(CUFFT_INVALID_TYPE), + error_entry(CUFFT_INVALID_VALUE), + error_entry(CUFFT_INTERNAL_ERROR), + error_entry(CUFFT_EXEC_FAILED), + error_entry(CUFFT_SETUP_FAILED), + error_entry(CUFFT_INVALID_SIZE), + error_entry(CUFFT_UNALIGNED_DATA) + }; + + struct CufftErrorComparer + { + CufftErrorComparer(int code_): code(code_) {} + bool operator()(const CufftError& other) const + { + return other.code == code; + } + int code; + }; + + const int cufft_error_num = sizeof(cufft_errors) / sizeof(cufft_errors[0]); + } namespace cv @@ -138,6 +175,26 @@ namespace cv cv::error( cv::Exception(CV_GpuNppCallError, getNppErrorString(err), func, file, line) ); } + const string getCufftErrorString(int err_code) + { + const CufftError* cufft_error = std::find_if( + cufft_errors, cufft_errors + cufft_error_num, + CufftErrorComparer(err_code)); + + bool found = cufft_error != cufft_errors + cufft_error_num; + + std::stringstream ss; + ss << (found ? cufft_error->message : "Unknown error code"); + ss << " [Code = " << err_code << "]"; + + return ss.str(); + } + + void cufftError(int err, const char *file, const int line, const char *func) + { + cv::error(cv::Exception(CV_GpuCufftCallError, getCufftErrorString(err), func, file, line)); + } + void error(const char *error_string, const char *file, const int line, const char *func) { int code = CV_GpuApiCallError; diff --git a/modules/gpu/src/match_template.cpp b/modules/gpu/src/match_template.cpp index e78badb16..70141371a 100644 --- a/modules/gpu/src/match_template.cpp +++ b/modules/gpu/src/match_template.cpp @@ -52,8 +52,6 @@ void cv::gpu::matchTemplate(const GpuMat&, const GpuMat&, GpuMat&, int) { throw_ #else -#include - namespace cv { namespace gpu { namespace imgproc { void multiplyAndNormalizeSpects(int n, float scale, const cufftComplex* a, @@ -271,27 +269,27 @@ namespace cufftReal* image_data; cufftReal* templ_data; cufftReal* result_data; - cudaMalloc((void**)&image_data, sizeof(cufftReal) * dft_size.area()); - cudaMalloc((void**)&templ_data, sizeof(cufftReal) * dft_size.area()); - cudaMalloc((void**)&result_data, sizeof(cufftReal) * dft_size.area()); + cudaSafeCall(cudaMalloc((void**)&image_data, sizeof(cufftReal) * dft_size.area())); + cudaSafeCall(cudaMalloc((void**)&templ_data, sizeof(cufftReal) * dft_size.area())); + cudaSafeCall(cudaMalloc((void**)&result_data, sizeof(cufftReal) * dft_size.area())); int spect_len = dft_size.height * (dft_size.width / 2 + 1); cufftComplex* image_spect; cufftComplex* templ_spect; cufftComplex* result_spect; - cudaMalloc((void**)&image_spect, sizeof(cufftComplex) * spect_len); - cudaMalloc((void**)&templ_spect, sizeof(cufftComplex) * spect_len); - cudaMalloc((void**)&result_spect, sizeof(cufftComplex) * spect_len); + cudaSafeCall(cudaMalloc((void**)&image_spect, sizeof(cufftComplex) * spect_len)); + cudaSafeCall(cudaMalloc((void**)&templ_spect, sizeof(cufftComplex) * spect_len)); + cudaSafeCall(cudaMalloc((void**)&result_spect, sizeof(cufftComplex) * spect_len)); cufftHandle planR2C, planC2R; - CV_Assert(cufftPlan2d(&planC2R, dft_size.height, dft_size.width, CUFFT_C2R) == CUFFT_SUCCESS); - CV_Assert(cufftPlan2d(&planR2C, dft_size.height, dft_size.width, CUFFT_R2C) == CUFFT_SUCCESS); + cufftSafeCall(cufftPlan2d(&planC2R, dft_size.height, dft_size.width, CUFFT_C2R)); + cufftSafeCall(cufftPlan2d(&planR2C, dft_size.height, dft_size.width, CUFFT_R2C)); GpuMat templ_roi(templ.size(), CV_32S, templ.data, templ.step); GpuMat templ_block(dft_size, CV_32S, templ_data, dft_size.width * sizeof(cufftReal)); copyMakeBorder(templ_roi, templ_block, 0, templ_block.rows - templ_roi.rows, 0, templ_block.cols - templ_roi.cols, 0); - CV_Assert(cufftExecR2C(planR2C, templ_data, templ_spect) == CUFFT_SUCCESS); + cufftSafeCall(cufftExecR2C(planR2C, templ_data, templ_spect)); GpuMat image_block(dft_size, CV_32S, image_data, dft_size.width * sizeof(cufftReal)); @@ -306,10 +304,10 @@ namespace copyMakeBorder(image_roi, image_block, 0, image_block.rows - image_roi.rows, 0, image_block.cols - image_roi.cols, 0); - CV_Assert(cufftExecR2C(planR2C, image_data, image_spect) == CUFFT_SUCCESS); + cufftSafeCall(cufftExecR2C(planR2C, image_data, image_spect)); imgproc::multiplyAndNormalizeSpects(spect_len, 1.f / dft_size.area(), image_spect, templ_spect, result_spect); - CV_Assert(cufftExecC2R(planC2R, result_spect, result_data) == CUFFT_SUCCESS); + cufftSafeCall(cufftExecC2R(planC2R, result_spect, result_data)); Size result_roi_size; result_roi_size.width = min(x + block_size.width, result.cols) - x; @@ -320,15 +318,15 @@ namespace } } - cufftDestroy(planR2C); - cufftDestroy(planC2R); + cufftSafeCall(cufftDestroy(planR2C)); + cufftSafeCall(cufftDestroy(planC2R)); - cudaFree(image_spect); - cudaFree(templ_spect); - cudaFree(result_spect); - cudaFree(image_data); - cudaFree(templ_data); - cudaFree(result_data); + cudaSafeCall(cudaFree(image_spect)); + cudaSafeCall(cudaFree(templ_spect)); + cudaSafeCall(cudaFree(result_spect)); + cudaSafeCall(cudaFree(image_data)); + cudaSafeCall(cudaFree(templ_data)); + cudaSafeCall(cudaFree(result_data)); } diff --git a/modules/gpu/src/precomp.hpp b/modules/gpu/src/precomp.hpp index 195deaff3..c05366f4a 100644 --- a/modules/gpu/src/precomp.hpp +++ b/modules/gpu/src/precomp.hpp @@ -64,6 +64,7 @@ #include "internal_shared.hpp" #include "cuda_runtime_api.h" + #include "cufft.h" #include "opencv2/gpu/stream_accessor.hpp" #include "npp.h" #include "npp_staging.h"