diff --git a/conformity/opencv/common.h b/conformity/opencv/common.h index b34720445542a193f26ff3f3405533f38d4d2c46..43dbfe4c9654a3f4d5b171fd4ce609944b58c741 100644 --- a/conformity/opencv/common.h +++ b/conformity/opencv/common.h @@ -21,7 +21,8 @@ #include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" -#define KLEIDICV_CONFORMITY_SHM_ID "/opencv_kleidicv_conformity_check_shm" +#define KLEIDICV_CONFORMITY_SHM_ID0 "/opencv_kleidicv_conformity_check_shm0" +#define KLEIDICV_CONFORMITY_SHM_ID1 "/opencv_kleidicv_conformity_check_shm1" #define KLEIDICV_CONFORMITY_SHM_SIZE (1024 * 1024) #define KLEIDICV_CONFORMITY_REQUEST_MQ_ID \ @@ -211,6 +212,9 @@ class MessageQueue { } int last_cmd() const { return last_message_.cmd; } + int last_ndims() const { return last_message_.ndims; } + const int* last_sizes() const { return last_message_.sizes; } + int last_type() const { return last_message_.type; } cv::Mat cv_mat_from_last_msg() const { return sm_.cv_mat(last_message_.ndims, last_message_.sizes, diff --git a/conformity/opencv/manager.cpp b/conformity/opencv/manager.cpp index 99bc18c4cae3237a72c126137cf398d107931538..5b3c29b1829fe7cbed3bccf3802092f760a049d4 100644 --- a/conformity/opencv/manager.cpp +++ b/conformity/opencv/manager.cpp @@ -40,15 +40,19 @@ int main(int argc, char** argv) { throw ExceptionWithErrno("Cannot start subordinate executable"); } - RecreatedSharedMemory sm{KLEIDICV_CONFORMITY_SHM_ID, - KLEIDICV_CONFORMITY_SHM_SIZE}; - RecreatedMessageQueue request_queue{KLEIDICV_CONFORMITY_REQUEST_MQ_ID, sm}; - RecreatedMessageQueue reply_queue{KLEIDICV_CONFORMITY_REPLY_MQ_ID, sm}; + RecreatedSharedMemory sm0{KLEIDICV_CONFORMITY_SHM_ID0, + KLEIDICV_CONFORMITY_SHM_SIZE}; + RecreatedSharedMemory sm1{KLEIDICV_CONFORMITY_SHM_ID1, + KLEIDICV_CONFORMITY_SHM_SIZE}; + RecreatedMessageQueue request_queue{KLEIDICV_CONFORMITY_REQUEST_MQ_ID, sm0}; + RecreatedMessageQueue reply_queue{KLEIDICV_CONFORMITY_REPLY_MQ_ID, sm0}; + + ExtraSMType extrasm = {&sm1}; // Let subordinate know that init is done kill(child_pid, SIGUSR1); - int test_results = run_tests(request_queue, reply_queue); + int test_results = run_tests(request_queue, reply_queue, extrasm); // Wait for subordinate to exit wait(NULL); diff --git a/conformity/opencv/subordinate.cpp b/conformity/opencv/subordinate.cpp index 4291aaa4821b1339ee697685ca6f8011660c737d..e557157cb50078f25958c133a919b59c65770939 100644 --- a/conformity/opencv/subordinate.cpp +++ b/conformity/opencv/subordinate.cpp @@ -8,12 +8,16 @@ #include "tests.h" int main(void) { - OpenedSharedMemory sm{KLEIDICV_CONFORMITY_SHM_ID, - KLEIDICV_CONFORMITY_SHM_SIZE}; - OpenedMessageQueue request_queue{KLEIDICV_CONFORMITY_REQUEST_MQ_ID, sm}; - OpenedMessageQueue reply_queue{KLEIDICV_CONFORMITY_REPLY_MQ_ID, sm}; + OpenedSharedMemory sm0{KLEIDICV_CONFORMITY_SHM_ID0, + KLEIDICV_CONFORMITY_SHM_SIZE}; + OpenedSharedMemory sm1{KLEIDICV_CONFORMITY_SHM_ID1, + KLEIDICV_CONFORMITY_SHM_SIZE}; + OpenedMessageQueue request_queue{KLEIDICV_CONFORMITY_REQUEST_MQ_ID, sm0}; + OpenedMessageQueue reply_queue{KLEIDICV_CONFORMITY_REPLY_MQ_ID, sm0}; - wait_for_requests(request_queue, reply_queue); + ExtraSMType extrasm = {&sm1}; + + wait_for_requests(request_queue, reply_queue, extrasm); std::cout << "Subordinate exits normally" << std::endl; } diff --git a/conformity/opencv/test_exp.cpp b/conformity/opencv/test_exp.cpp index eb97c96ac5d4c23758498efc0afdc1e83c2a0da8..242bf2e778411eded7e3be94fe2e2a942134344c 100644 --- a/conformity/opencv/test_exp.cpp +++ b/conformity/opencv/test_exp.cpp @@ -10,16 +10,20 @@ #include "opencv2/core/hal/interface.h" -static cv::Mat exec_exp(cv::Mat& input_mat) { +static cv::Mat exec_exp_bare(cv::Mat& input_mat) { cv::Mat result; cv::exp(input_mat, result); return result; } +cv::Mat exec_exp(cv::Mat& input, ExtraSMType, OpenedMessageQueue&) { + return exec_exp_bare(input); +} + #if MANAGER template bool test_exp(int index, RecreatedMessageQueue& request_queue, - RecreatedMessageQueue& reply_queue) { + RecreatedMessageQueue& reply_queue, ExtraSMType) { cv::RNG rng(0); for (size_t x = 5; x <= 16; ++x) { @@ -27,7 +31,7 @@ bool test_exp(int index, RecreatedMessageQueue& request_queue, cv::Mat input_mat(x, y, CV_32FC(Channels)); // Use inputs where results are not flowing over or under rng.fill(input_mat, cv::RNG::UNIFORM, -80.0, 80.0); - cv::Mat actual_mat = exec_exp(input_mat); + cv::Mat actual_mat = exec_exp_bare(input_mat); cv::Mat expected_mat = get_expected_from_subordinate( index, request_queue, reply_queue, input_mat); diff --git a/conformity/opencv/test_gaussian_blur.cpp b/conformity/opencv/test_gaussian_blur.cpp index f56f4a9333458ab02faa09d9006def5d096dd622..e985c3d4c577015da366d34575e1b15006ebe846 100644 --- a/conformity/opencv/test_gaussian_blur.cpp +++ b/conformity/opencv/test_gaussian_blur.cpp @@ -7,17 +7,22 @@ #include template -cv::Mat exec_gaussian_blur(cv::Mat& input) { +cv::Mat exec_gaussian_blur_bare(cv::Mat& input) { cv::Size kernel(KernelSize, KernelSize); cv::Mat result; cv::GaussianBlur(input, result, kernel, 0, 0, BorderType); return result; } +template +cv::Mat exec_gaussian_blur(cv::Mat& input, ExtraSMType, OpenedMessageQueue&) { + return exec_gaussian_blur_bare(input); +} + #if MANAGER template bool test_gaussian_blur(int index, RecreatedMessageQueue& request_queue, - RecreatedMessageQueue& reply_queue) { + RecreatedMessageQueue& reply_queue, ExtraSMType) { cv::RNG rng(0); for (size_t x = 5; x <= 16; ++x) { @@ -25,7 +30,7 @@ bool test_gaussian_blur(int index, RecreatedMessageQueue& request_queue, cv::Mat input(x, y, CV_8UC(Channels)); rng.fill(input, cv::RNG::UNIFORM, 0, 255); - cv::Mat actual = exec_gaussian_blur(input); + cv::Mat actual = exec_gaussian_blur_bare(input); cv::Mat expected = get_expected_from_subordinate(index, request_queue, reply_queue, input); diff --git a/conformity/opencv/test_min_max.cpp b/conformity/opencv/test_min_max.cpp index 9f9731e56e6fe0ee4cf85638cb2997f85b81afb1..79d7262568216ba69609db5820eaebf4a40a8bcf 100644 --- a/conformity/opencv/test_min_max.cpp +++ b/conformity/opencv/test_min_max.cpp @@ -8,7 +8,7 @@ #include template -cv::Mat exec_min_max(cv::Mat& input) { +cv::Mat exec_min_max_bare(cv::Mat& input) { double minVal, maxVal; if constexpr (GetIndex) { cv::Mat result(2 + 2 * input.dims, 1, CV_32SC1); @@ -27,10 +27,15 @@ cv::Mat exec_min_max(cv::Mat& input) { } } +template +cv::Mat exec_min_max(cv::Mat& input, ExtraSMType, OpenedMessageQueue&) { + return exec_min_max_bare(input); +} + #if MANAGER template bool test_min_max(int index, RecreatedMessageQueue& request_queue, - RecreatedMessageQueue& reply_queue) { + RecreatedMessageQueue& reply_queue, ExtraSMType) { cv::RNG rng(0); constexpr size_t Channels = (Format >> CV_CN_SHIFT) + 1; @@ -46,7 +51,7 @@ bool test_min_max(int index, RecreatedMessageQueue& request_queue, pixel[rng.next() % Channels] = rng.next(); } - cv::Mat actual = exec_min_max(input); + cv::Mat actual = exec_min_max_bare(input); cv::Mat expected = get_expected_from_subordinate(index, request_queue, reply_queue, input); if (are_matrices_different(0, actual, expected)) { @@ -61,7 +66,7 @@ bool test_min_max(int index, RecreatedMessageQueue& request_queue, cv::Mat input(std::vector{x, y, z}, Format); rng.fill(input, cv::RNG::UNIFORM, std::numeric_limits::lowest(), std::numeric_limits::max()); - cv::Mat actual = exec_min_max(input); + cv::Mat actual = exec_min_max_bare(input); cv::Mat expected = get_expected_from_subordinate(index, request_queue, reply_queue, input); if (are_matrices_different(0, actual, expected)) { diff --git a/conformity/opencv/test_rgb2yuv.cpp b/conformity/opencv/test_rgb2yuv.cpp index e6633bf3c8fa95cd3f62bd6a3bdf7c5950137a68..41d1293ec4f896c11d97fbc8964e7b40c9dfaebe 100644 --- a/conformity/opencv/test_rgb2yuv.cpp +++ b/conformity/opencv/test_rgb2yuv.cpp @@ -7,7 +7,7 @@ #include template -cv::Mat exec_rgb2yuv(cv::Mat& input) { +cv::Mat exec_rgb2yuv_bare(cv::Mat& input) { cv::Mat result; if constexpr (SwitchBlue) { cv::cvtColor(input, result, cv::COLOR_BGR2YUV); @@ -17,10 +17,15 @@ cv::Mat exec_rgb2yuv(cv::Mat& input) { return result; } +template +cv::Mat exec_rgb2yuv(cv::Mat& input, ExtraSMType, OpenedMessageQueue&) { + return exec_rgb2yuv_bare(input); +} + #if MANAGER template bool test_rgb2yuv(int index, RecreatedMessageQueue& request_queue, - RecreatedMessageQueue& reply_queue) { + RecreatedMessageQueue& reply_queue, ExtraSMType) { cv::RNG rng(0); for (size_t x = 5; x <= 16; ++x) { @@ -28,7 +33,7 @@ bool test_rgb2yuv(int index, RecreatedMessageQueue& request_queue, cv::Mat input(x, y, CV_8UC(Channels)); rng.fill(input, cv::RNG::UNIFORM, 0, 255); - cv::Mat actual = exec_rgb2yuv(input); + cv::Mat actual = exec_rgb2yuv_bare(input); cv::Mat expected = get_expected_from_subordinate(index, request_queue, reply_queue, input); diff --git a/conformity/opencv/test_sobel.cpp b/conformity/opencv/test_sobel.cpp index 473e153a651526b259a2c64889bf46bd233f205a..1c7505dc624f214009c860120cef546eb84faf9c 100644 --- a/conformity/opencv/test_sobel.cpp +++ b/conformity/opencv/test_sobel.cpp @@ -7,7 +7,7 @@ #include template -cv::Mat exec_sobel(cv::Mat& input) { +cv::Mat exec_sobel_bare(cv::Mat& input) { cv::Mat result; if constexpr (Vertical) { cv::Sobel(input, result, CV_16S, 0, 1, 3, 1.0, 0.0, cv::BORDER_REPLICATE); @@ -17,10 +17,15 @@ cv::Mat exec_sobel(cv::Mat& input) { return result; } +template +cv::Mat exec_sobel(cv::Mat& input, ExtraSMType, OpenedMessageQueue&) { + return exec_sobel_bare(input); +} + #if MANAGER template bool test_sobel(int index, RecreatedMessageQueue& request_queue, - RecreatedMessageQueue& reply_queue) { + RecreatedMessageQueue& reply_queue, ExtraSMType) { cv::RNG rng(0); for (size_t x = 5; x <= 16; ++x) { @@ -28,7 +33,7 @@ bool test_sobel(int index, RecreatedMessageQueue& request_queue, cv::Mat input(x, y, CV_8UC(Channels)); rng.fill(input, cv::RNG::UNIFORM, 0, 255); - cv::Mat actual = exec_sobel(input); + cv::Mat actual = exec_sobel_bare(input); cv::Mat expected = get_expected_from_subordinate(index, request_queue, reply_queue, input); diff --git a/conformity/opencv/tests.cpp b/conformity/opencv/tests.cpp index 657d5551e77f5e3da6e021a7c3ed6b5616ce6353..c61e07a0bdaccdbb8183ecf5d39867ce22e41d38 100644 --- a/conformity/opencv/tests.cpp +++ b/conformity/opencv/tests.cpp @@ -34,6 +34,36 @@ std::vector all_tests = merge_tests({ exp_tests_get, }); +template <> +int cv_type(size_t channels) { + return CV_8UC(channels); +} + +template <> +int cv_type(size_t channels) { + return CV_8SC(channels); +} + +template <> +int cv_type(size_t channels) { + return CV_16UC(channels); +} + +template <> +int cv_type(size_t channels) { + return CV_16SC(channels); +} + +template <> +int cv_type(size_t channels) { + return CV_32SC(channels); +} + +template <> +int cv_type(size_t channels) { + return CV_32FC(channels); +} + #if MANAGER void fail_print_matrices(size_t height, size_t width, cv::Mat& input, cv::Mat& manager_result, cv::Mat& subord_result) { @@ -64,11 +94,11 @@ cv::Mat get_expected_from_subordinate(int index, #if MANAGER int run_tests(RecreatedMessageQueue& request_queue, - RecreatedMessageQueue& reply_queue) { + RecreatedMessageQueue& reply_queue, ExtraSMType extrasm) { int ret_val = 0; for (int i = 0; i < static_cast(all_tests.size()); ++i) { std::cout << "Testing " + all_tests[i].first << std::endl; - if (all_tests[i].second(i, request_queue, reply_queue)) { + if (all_tests[i].second(i, request_queue, reply_queue, extrasm)) { ret_val = 1; } } @@ -78,7 +108,7 @@ int run_tests(RecreatedMessageQueue& request_queue, } #else void wait_for_requests(OpenedMessageQueue& request_queue, - OpenedMessageQueue& reply_queue) { + OpenedMessageQueue& reply_queue, ExtraSMType extrasm) { while (true) { request_queue.wait(); int cmd = request_queue.last_cmd(); @@ -93,8 +123,9 @@ void wait_for_requests(OpenedMessageQueue& request_queue, } cv::Mat input = request_queue.cv_mat_from_last_msg(); - cv::Mat result = all_tests[cmd].second(input); + cv::Mat result = all_tests[cmd].second(input, extrasm, request_queue); reply_queue.reply_operation(cmd, result); } } + #endif diff --git a/conformity/opencv/tests.h b/conformity/opencv/tests.h index cce5aefc46873029b6984591c514c6bdc2e0aea4..0be2e1e90ed8abd46310f49dd2a68f4c2f599666 100644 --- a/conformity/opencv/tests.h +++ b/conformity/opencv/tests.h @@ -11,6 +11,15 @@ #include "common.h" +// By default (one input), Manager and Subordinate communicate using one +// SharedMemory instance. To allow more inputs, more such instances are +// required. The amount of 'extra' instances is stored here. +static constexpr size_t nr_of_extra_shared_memories = 1; + +// Template for mapping CPP types to OpenCV types +template +int cv_type(size_t channels); + #if MANAGER template static auto abs_diff(T a, T b) { @@ -77,19 +86,28 @@ cv::Mat get_expected_from_subordinate(int index, RecreatedMessageQueue& reply_queue, cv::Mat& input); +using ExtraSMType = + std::array; + int run_tests(RecreatedMessageQueue& request_queue, - RecreatedMessageQueue& reply_queue); + RecreatedMessageQueue& reply_queue, ExtraSMType extrasm); typedef bool (*test_function)(int index, RecreatedMessageQueue& request_queue, - RecreatedMessageQueue& reply_queue); + RecreatedMessageQueue& reply_queue, + ExtraSMType extrasm); using test = std::pair; #define TEST(name, test_func, x) \ { name, test_func } #else + +using ExtraSMType = + std::array; + void wait_for_requests(OpenedMessageQueue& request_queue, - OpenedMessageQueue& reply_queue); + OpenedMessageQueue& reply_queue, ExtraSMType extrasm); -typedef cv::Mat (*exec_function)(cv::Mat& input); +typedef cv::Mat (*exec_function)(cv::Mat& input, ExtraSMType extrasm, + OpenedMessageQueue& queue); using test = std::pair; #define TEST(name, x, exec_func) \ { name, exec_func }