diff --git a/modules/cudaarithm/test/test_event.cpp b/modules/cudaarithm/test/test_event.cpp new file mode 100644 index 000000000..375c51d0d --- /dev/null +++ b/modules/cudaarithm/test/test_event.cpp @@ -0,0 +1,104 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +#include "test_precomp.hpp" + +#ifdef HAVE_CUDA + +#include + +#include "opencv2/core/cuda.hpp" +#include "opencv2/core/cuda_stream_accessor.hpp" +#include "opencv2/ts/cuda_test.hpp" + +namespace opencv_test { namespace { + +struct AsyncEvent : testing::TestWithParam +{ + cv::cuda::HostMem src; + cv::cuda::GpuMat d_src; + + cv::cuda::HostMem dst; + cv::cuda::GpuMat d_dst; + + cv::cuda::Stream stream; + + virtual void SetUp() + { + cv::cuda::DeviceInfo devInfo = GetParam(); + cv::cuda::setDevice(devInfo.deviceID()); + + src = cv::cuda::HostMem(cv::cuda::HostMem::PAGE_LOCKED); + + cv::Mat m = randomMat(cv::Size(128, 128), CV_8UC1); + m.copyTo(src); + } +}; + +void deviceWork(void* userData) +{ + AsyncEvent* test = reinterpret_cast(userData); + test->d_src.upload(test->src, test->stream); + test->d_src.convertTo(test->d_dst, CV_32S, test->stream); + test->d_dst.download(test->dst, test->stream); +} + +CUDA_TEST_P(AsyncEvent, WrapEvent) +{ + cudaEvent_t cuda_event = NULL; + ASSERT_EQ(cudaSuccess, cudaEventCreate(&cuda_event)); + { + cv::cuda::Event cudaEvent = cv::cuda::EventAccessor::wrapEvent(cuda_event); + deviceWork(this); + cudaEvent.record(stream); + cudaEvent.waitForCompletion(); + cv::Mat dst_gold; + src.createMatHeader().convertTo(dst_gold, CV_32S); + ASSERT_MAT_NEAR(dst_gold, dst, 0); + } + ASSERT_EQ(cudaSuccess, cudaEventDestroy(cuda_event)); +} + +CUDA_TEST_P(AsyncEvent, WithFlags) +{ + cv::cuda::Event cudaEvent = cv::cuda::Event(cv::cuda::Event::CreateFlags::BLOCKING_SYNC); + deviceWork(this); + cudaEvent.record(stream); + cudaEvent.waitForCompletion(); + cv::Mat dst_gold; + src.createMatHeader().convertTo(dst_gold, CV_32S); + ASSERT_MAT_NEAR(dst_gold, dst, 0); +} + +CUDA_TEST_P(AsyncEvent, Timing) +{ + const std::vector eventFlags = { cv::cuda::Event::CreateFlags::BLOCKING_SYNC , cv::cuda::Event::CreateFlags::BLOCKING_SYNC | Event::CreateFlags::DISABLE_TIMING }; + const std::vector shouldFail = { false, true }; + for (size_t i = 0; i < eventFlags.size(); i++) { + const auto& flags = eventFlags.at(i); + cv::cuda::Event startEvent = cv::cuda::Event(flags); + cv::cuda::Event stopEvent = cv::cuda::Event(flags); + startEvent.record(stream); + deviceWork(this); + stopEvent.record(stream); + stopEvent.waitForCompletion(); + cv::Mat dst_gold; + src.createMatHeader().convertTo(dst_gold, CV_32S); + ASSERT_MAT_NEAR(dst_gold, dst, 0); + bool failed = false; + try { + const double elTimeMs = Event::elapsedTime(startEvent, stopEvent); + ASSERT_GT(elTimeMs, 0); + } + catch (cv::Exception ex) { + failed = true; + } + ASSERT_EQ(failed, shouldFail.at(i)); + } +} + +INSTANTIATE_TEST_CASE_P(CUDA_Event, AsyncEvent, ALL_DEVICES); + +}} // namespace +#endif // HAVE_CUDA