| /* |
| |
| * Copyright (c) 2012-2017 The Khronos Group Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "test_engine/test.h" |
| |
| #include <VX/vx.h> |
| #include <VX/vxu.h> |
| |
| #include <math.h> |
| |
| #ifdef _MSC_VER |
| #define ONE_255 (1.0f/255) |
| #else |
| #define ONE_255 0x1.010102p-8f |
| #endif |
| #define ONE_2_0 1.0f |
| #define ONE_2_1 (1.0f/(1<<1)) |
| #define ONE_2_2 (1.0f/(1<<2)) |
| #define ONE_2_3 (1.0f/(1<<3)) |
| #define ONE_2_4 (1.0f/(1<<4)) |
| #define ONE_2_5 (1.0f/(1<<5)) |
| #define ONE_2_6 (1.0f/(1<<6)) |
| #define ONE_2_7 (1.0f/(1<<7)) |
| #define ONE_2_8 (1.0f/(1<<8)) |
| #define ONE_2_9 (1.0f/(1<<9)) |
| #define ONE_2_10 (1.0f/(1<<10)) |
| #define ONE_2_11 (1.0f/(1<<11)) |
| #define ONE_2_12 (1.0f/(1<<12)) |
| #define ONE_2_13 (1.0f/(1<<13)) |
| #define ONE_2_14 (1.0f/(1<<14)) |
| #define ONE_2_15 (1.0f/(1<<15)) |
| |
| #define ONE_255_STR "(1/255)" |
| #define ONE_2_0_STR "(1/2^0)" |
| #define ONE_2_1_STR "(1/2^1)" |
| #define ONE_2_2_STR "(1/2^2)" |
| #define ONE_2_3_STR "(1/2^3)" |
| #define ONE_2_4_STR "(1/2^4)" |
| #define ONE_2_5_STR "(1/2^5)" |
| #define ONE_2_6_STR "(1/2^6)" |
| #define ONE_2_7_STR "(1/2^7)" |
| #define ONE_2_8_STR "(1/2^8)" |
| #define ONE_2_9_STR "(1/2^9)" |
| #define ONE_2_10_STR "(1/2^10)" |
| #define ONE_2_11_STR "(1/2^11)" |
| #define ONE_2_12_STR "(1/2^12)" |
| #define ONE_2_13_STR "(1/2^13)" |
| #define ONE_2_14_STR "(1/2^14)" |
| #define ONE_2_15_STR "(1/2^15)" |
| |
| //#define CT_EXECUTE_ASYNC |
| |
| static void referenceMultiply(CT_Image src0, CT_Image src1, CT_Image dst, CT_Image dst_plus_1, vx_float32 scale, enum vx_convert_policy_e policy) |
| { |
| int32_t min_bound, max_bound; |
| uint32_t i, j; |
| |
| ASSERT(src0 && src1 && dst && dst_plus_1); |
| ASSERT(src0->width == src1->width && src0->width == dst->width && src0->width == dst_plus_1->width); |
| ASSERT(src0->height == src1->height && src0->height == dst->height && src0->height == dst_plus_1->height); |
| ASSERT(dst->format == dst_plus_1->format); |
| |
| switch (policy) |
| { |
| case VX_CONVERT_POLICY_SATURATE: |
| if (dst->format == VX_DF_IMAGE_U8) |
| { |
| min_bound = 0; |
| max_bound = 255; |
| } |
| else if (dst->format == VX_DF_IMAGE_S16) |
| { |
| min_bound = -32768; |
| max_bound = 32767; |
| } |
| else |
| FAIL("Unsupported result format: (%.4s)", &dst->format); |
| break; |
| case VX_CONVERT_POLICY_WRAP: |
| min_bound = INT32_MIN; |
| max_bound = INT32_MAX; |
| break; |
| default: FAIL("Unknown owerflow policy"); break; |
| }; |
| |
| #define MULTIPLY_LOOP(s0, s1, r) \ |
| do{ \ |
| for (i = 0; i < dst->height; ++i) \ |
| for (j = 0; j < dst->width; ++j) \ |
| { \ |
| int32_t val0 = src0->data.s0[i * src0->stride + j]; \ |
| int32_t val1 = src1->data.s1[i * src1->stride + j]; \ |
| /* use double precision because in S16*S16 case (val0*val1) can be not representable as float */\ |
| int32_t res0 = (int32_t)floor(((double)(val0 * val1)) * scale); \ |
| int32_t res1 = res0 + 1; \ |
| dst->data.r[i * dst->stride + j] = (res0 < min_bound ? min_bound : \ |
| (res0 > max_bound ? max_bound : res0)); \ |
| dst_plus_1->data.r[i * dst_plus_1->stride + j] = (res1 < min_bound ? min_bound : \ |
| (res1 > max_bound ? max_bound : res1)); \ |
| } \ |
| }while(0) |
| |
| if (src0->format == VX_DF_IMAGE_U8 && src1->format == VX_DF_IMAGE_U8 && dst->format == VX_DF_IMAGE_U8) |
| MULTIPLY_LOOP(y, y, y); |
| else if (src0->format == VX_DF_IMAGE_U8 && src1->format == VX_DF_IMAGE_U8 && dst->format == VX_DF_IMAGE_S16) |
| MULTIPLY_LOOP(y, y, s16); |
| else if (src0->format == VX_DF_IMAGE_U8 && src1->format == VX_DF_IMAGE_S16 && dst->format == VX_DF_IMAGE_S16) |
| MULTIPLY_LOOP(y, s16, s16); |
| else if (src0->format == VX_DF_IMAGE_S16 && src1->format == VX_DF_IMAGE_U8 && dst->format == VX_DF_IMAGE_S16) |
| MULTIPLY_LOOP(s16, y, s16); |
| else if (src0->format == VX_DF_IMAGE_S16 && src1->format == VX_DF_IMAGE_S16 && dst->format == VX_DF_IMAGE_S16) |
| MULTIPLY_LOOP(s16, s16, s16); |
| else |
| FAIL("Unsupported combination of argument formats: %.4s + %.4s = %.4s", &src0->format, &src1->format, &dst->format); |
| |
| #undef MULTIPLY_LOOP |
| } |
| |
| typedef struct { |
| const char* name; |
| enum vx_convert_policy_e overflow_policy; |
| int width, height; |
| vx_df_image arg1_format, arg2_format, result_format; |
| enum vx_round_policy_e round_policy; |
| vx_float32 scale; |
| } formats_arg, fuzzy_arg; |
| |
| #define FORMATS_ARG(owp, f1, f2, fr, rp, scale) \ |
| ARG(#owp "/" #rp " " #f1 "*" #f2 "*" scale##_STR "=" #fr, \ |
| VX_CONVERT_POLICY_##owp, 0, 0, VX_DF_IMAGE_##f1, VX_DF_IMAGE_##f2, VX_DF_IMAGE_##fr, VX_ROUND_POLICY_##rp, scale) |
| |
| #define FUZZY_ARG(owp, w, h, f1, f2, fr, rp, scale) \ |
| ARG(#owp "/" #rp " " #w "x" #h " " #f1 "*" #f2 "*" scale##_STR "=" #fr, \ |
| VX_CONVERT_POLICY_##owp, w, h, VX_DF_IMAGE_##f1, VX_DF_IMAGE_##f2, VX_DF_IMAGE_##fr, VX_ROUND_POLICY_##rp, scale) |
| |
| #define APPEND_SCALE(macro, ...) \ |
| CT_EXPAND(macro(__VA_ARGS__, TO_NEAREST_EVEN, ONE_255)), \ |
| CT_EXPAND(macro(__VA_ARGS__, TO_ZERO, ONE_2_0)), \ |
| CT_EXPAND(macro(__VA_ARGS__, TO_ZERO, ONE_2_1)), \ |
| CT_EXPAND(macro(__VA_ARGS__, TO_ZERO, ONE_2_2)), \ |
| CT_EXPAND(macro(__VA_ARGS__, TO_ZERO, ONE_2_3)), \ |
| CT_EXPAND(macro(__VA_ARGS__, TO_ZERO, ONE_2_4)), \ |
| CT_EXPAND(macro(__VA_ARGS__, TO_ZERO, ONE_2_5)), \ |
| CT_EXPAND(macro(__VA_ARGS__, TO_ZERO, ONE_2_6)), \ |
| CT_EXPAND(macro(__VA_ARGS__, TO_ZERO, ONE_2_7)), \ |
| CT_EXPAND(macro(__VA_ARGS__, TO_ZERO, ONE_2_8)), \ |
| CT_EXPAND(macro(__VA_ARGS__, TO_ZERO, ONE_2_9)), \ |
| CT_EXPAND(macro(__VA_ARGS__, TO_ZERO, ONE_2_10)), \ |
| CT_EXPAND(macro(__VA_ARGS__, TO_ZERO, ONE_2_11)), \ |
| CT_EXPAND(macro(__VA_ARGS__, TO_ZERO, ONE_2_12)), \ |
| CT_EXPAND(macro(__VA_ARGS__, TO_ZERO, ONE_2_13)), \ |
| CT_EXPAND(macro(__VA_ARGS__, TO_ZERO, ONE_2_14)), \ |
| CT_EXPAND(macro(__VA_ARGS__, TO_ZERO, ONE_2_15)) |
| |
| #define MUL_INVALID_FORMATS(owp) \ |
| APPEND_SCALE(FORMATS_ARG, owp, S16, S16, U8), \ |
| APPEND_SCALE(FORMATS_ARG, owp, S16, U8, U8), \ |
| APPEND_SCALE(FORMATS_ARG, owp, U8, S16, U8) |
| |
| #define MUL_INFERENCE_FORMATS(opw) \ |
| APPEND_SCALE(FORMATS_ARG, opw, S16, S16, S16), \ |
| APPEND_SCALE(FORMATS_ARG, opw, S16, U8, S16), \ |
| APPEND_SCALE(FORMATS_ARG, opw, U8, S16, S16), \ |
| APPEND_SCALE(FORMATS_ARG, opw, U8, U8, S16) |
| |
| #define MUL_VALID_FORMATS(opw) MUL_INFERENCE_FORMATS(opw), APPEND_SCALE(FORMATS_ARG, opw, U8, U8, U8) |
| |
| #define MUL_FUZZY_ARGS(owp) \ |
| APPEND_SCALE(FUZZY_ARG, owp, 640, 480, U8, U8, U8), \ |
| APPEND_SCALE(FUZZY_ARG, owp, 640, 480, U8, U8, S16), \ |
| APPEND_SCALE(FUZZY_ARG, owp, 640, 480, U8, S16, S16), \ |
| APPEND_SCALE(FUZZY_ARG, owp, 640, 480, S16, U8, S16), \ |
| APPEND_SCALE(FUZZY_ARG, owp, 640, 480, S16, S16, S16), \ |
| \ |
| ARG_EXTENDED_BEGIN(), \ |
| APPEND_SCALE(FUZZY_ARG, owp, 15, 15, U8, U8, U8), \ |
| APPEND_SCALE(FUZZY_ARG, owp, 15, 15, U8, U8, S16), \ |
| APPEND_SCALE(FUZZY_ARG, owp, 15, 15, U8, S16, S16), \ |
| APPEND_SCALE(FUZZY_ARG, owp, 15, 15, S16, U8, S16), \ |
| APPEND_SCALE(FUZZY_ARG, owp, 15, 15, S16, S16, S16), \ |
| \ |
| APPEND_SCALE(FUZZY_ARG, owp, 1280, 720, U8, U8, U8), \ |
| APPEND_SCALE(FUZZY_ARG, owp, 1280, 720, U8, U8, S16), \ |
| APPEND_SCALE(FUZZY_ARG, owp, 1280, 720, U8, S16, S16), \ |
| APPEND_SCALE(FUZZY_ARG, owp, 1280, 720, S16, U8, S16), \ |
| APPEND_SCALE(FUZZY_ARG, owp, 1280, 720, S16, S16, S16), \ |
| ARG_EXTENDED_END() |
| |
| TESTCASE(vxuMultiply, CT_VXContext, ct_setup_vx_context, 0) |
| TESTCASE(vxMultiply, CT_VXContext, ct_setup_vx_context, 0) |
| |
| TEST_WITH_ARG(vxuMultiply, testNegativeFormat, formats_arg, MUL_INVALID_FORMATS(SATURATE), MUL_INVALID_FORMATS(WRAP)) |
| { |
| vx_image src1, src2, dst; |
| vx_float32 scale_val = arg_->scale; |
| vx_context context = context_->vx_context_; |
| |
| ASSERT_VX_OBJECT(src1 = vxCreateImage(context, 32, 32, arg_->arg1_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(src2 = vxCreateImage(context, 32, 32, arg_->arg2_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(dst = vxCreateImage(context, 32, 32, arg_->result_format), VX_TYPE_IMAGE); |
| |
| // initialize to guarantee that images are allocated |
| ASSERT_NO_FAILURE(ct_fill_image_random(src1, &CT()->seed_)); |
| ASSERT_NO_FAILURE(ct_fill_image_random(src2, &CT()->seed_)); |
| |
| // The output image can be VX_DF_IMAGE_U8 only if both source images are |
| // VX_DF_IMAGE_U8 and the output image is explicitly set to VX_DF_IMAGE_U8. It is |
| // otherwise VX_DF_IMAGE_S16. |
| ASSERT_NE_VX_STATUS(VX_SUCCESS, vxuMultiply(context, src1, src2, scale_val, arg_->overflow_policy, arg_->round_policy, dst)); |
| |
| VX_CALL(vxReleaseImage(&src1)); |
| VX_CALL(vxReleaseImage(&src2)); |
| VX_CALL(vxReleaseImage(&dst)); |
| } |
| |
| TEST_WITH_ARG(vxMultiply, testNegativeFormat, formats_arg, MUL_INVALID_FORMATS(SATURATE), MUL_INVALID_FORMATS(WRAP)) |
| { |
| vx_image src1, src2, dst; |
| vx_graph graph; |
| vx_scalar scale; |
| vx_context context = context_->vx_context_; |
| |
| ASSERT_VX_OBJECT(graph = vxCreateGraph(context), VX_TYPE_GRAPH); |
| |
| ASSERT_VX_OBJECT(src1 = vxCreateImage(context, 32, 32, arg_->arg1_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(src2 = vxCreateImage(context, 32, 32, arg_->arg2_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(dst = vxCreateImage(context, 32, 32, arg_->result_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(scale = vxCreateScalar(context, VX_TYPE_FLOAT32, &arg_->scale), VX_TYPE_SCALAR); |
| |
| ASSERT_VX_OBJECT(vxMultiplyNode(graph, src1, src2, scale, arg_->overflow_policy, arg_->round_policy, dst), VX_TYPE_NODE); |
| |
| // The output image can be VX_DF_IMAGE_U8 only if both source images are |
| // VX_DF_IMAGE_U8 and the output image is explicitly set to VX_DF_IMAGE_U8. It is |
| // otherwise VX_DF_IMAGE_S16. |
| ASSERT_NE_VX_STATUS(VX_SUCCESS, vxVerifyGraph(graph)); |
| |
| VX_CALL(vxReleaseImage(&src1)); |
| VX_CALL(vxReleaseImage(&src2)); |
| VX_CALL(vxReleaseImage(&dst)); |
| VX_CALL(vxReleaseScalar(&scale)); |
| VX_CALL(vxReleaseGraph(&graph)); |
| } |
| |
| TEST_WITH_ARG(vxuMultiply, testNegativeSizes, formats_arg, MUL_VALID_FORMATS(SATURATE), MUL_VALID_FORMATS(WRAP)) |
| { |
| vx_image src1_32x32, src1_64x64, src2_32x32, src2_32x64, dst32x32, dst88x16; |
| vx_float32 scale_val = arg_->scale; |
| vx_context context = context_->vx_context_; |
| |
| ASSERT_VX_OBJECT(src1_32x32 = vxCreateImage(context, 32, 32, arg_->arg1_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(src1_64x64 = vxCreateImage(context, 64, 64, arg_->arg1_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(src2_32x32 = vxCreateImage(context, 32, 32, arg_->arg2_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(src2_32x64 = vxCreateImage(context, 32, 64, arg_->arg2_format), VX_TYPE_IMAGE); |
| |
| ASSERT_VX_OBJECT(dst32x32 = vxCreateImage(context, 32, 32, arg_->result_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(dst88x16 = vxCreateImage(context, 88, 16, arg_->result_format), VX_TYPE_IMAGE); |
| |
| // initialize to guarantee that images are allocated |
| ASSERT_NO_FAILURE(ct_fill_image_random(src1_32x32, &CT()->seed_)); |
| ASSERT_NO_FAILURE(ct_fill_image_random(src1_64x64, &CT()->seed_)); |
| ASSERT_NO_FAILURE(ct_fill_image_random(src2_32x32, &CT()->seed_)); |
| ASSERT_NO_FAILURE(ct_fill_image_random(src2_32x64, &CT()->seed_)); |
| |
| EXPECT_NE_VX_STATUS(VX_SUCCESS, vxuMultiply(context, src1_32x32, src2_32x32, scale_val, arg_->overflow_policy, arg_->round_policy, dst88x16)); |
| EXPECT_NE_VX_STATUS(VX_SUCCESS, vxuMultiply(context, src1_32x32, src2_32x64, scale_val, arg_->overflow_policy, arg_->round_policy, dst32x32)); |
| EXPECT_NE_VX_STATUS(VX_SUCCESS, vxuMultiply(context, src1_64x64, src2_32x32, scale_val, arg_->overflow_policy, arg_->round_policy, dst32x32)); |
| EXPECT_NE_VX_STATUS(VX_SUCCESS, vxuMultiply(context, src1_64x64, src2_32x64, scale_val, arg_->overflow_policy, arg_->round_policy, dst32x32)); |
| |
| VX_CALL(vxReleaseImage(&src1_32x32)); |
| VX_CALL(vxReleaseImage(&src2_32x32)); |
| VX_CALL(vxReleaseImage(&src1_64x64)); |
| VX_CALL(vxReleaseImage(&src2_32x64)); |
| VX_CALL(vxReleaseImage(&dst32x32)); |
| VX_CALL(vxReleaseImage(&dst88x16)); |
| } |
| |
| TEST_WITH_ARG(vxMultiply, testNegativeSizes, formats_arg, MUL_VALID_FORMATS(SATURATE), MUL_VALID_FORMATS(WRAP)) |
| { |
| vx_image src1_32x32, src1_64x64, src2_32x32, src2_32x64, dst32x32, dst88x16; |
| vx_graph graph1, graph2, graph3, graph4; |
| vx_scalar scale; |
| vx_context context = context_->vx_context_; |
| |
| ASSERT_VX_OBJECT(src1_32x32 = vxCreateImage(context, 32, 32, arg_->arg1_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(src1_64x64 = vxCreateImage(context, 64, 64, arg_->arg1_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(src2_32x32 = vxCreateImage(context, 32, 32, arg_->arg2_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(src2_32x64 = vxCreateImage(context, 32, 64, arg_->arg2_format), VX_TYPE_IMAGE); |
| |
| ASSERT_VX_OBJECT(dst32x32 = vxCreateImage(context, 32, 32, arg_->result_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(dst88x16 = vxCreateImage(context, 88, 16, arg_->result_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(scale = vxCreateScalar(context, VX_TYPE_FLOAT32, &arg_->scale), VX_TYPE_SCALAR); |
| |
| ASSERT_VX_OBJECT(graph1 = vxCreateGraph(context), VX_TYPE_GRAPH); |
| ASSERT_VX_OBJECT(vxMultiplyNode(graph1, src1_32x32, src2_32x32, scale, arg_->overflow_policy, arg_->round_policy, dst88x16), VX_TYPE_NODE); |
| EXPECT_NE_VX_STATUS(VX_SUCCESS, vxVerifyGraph(graph1)); |
| |
| ASSERT_VX_OBJECT(graph2 = vxCreateGraph(context), VX_TYPE_GRAPH); |
| ASSERT_VX_OBJECT(vxMultiplyNode(graph2, src1_32x32, src2_32x64, scale, arg_->overflow_policy, arg_->round_policy, dst32x32), VX_TYPE_NODE); |
| EXPECT_NE_VX_STATUS(VX_SUCCESS, vxVerifyGraph(graph2)); |
| |
| ASSERT_VX_OBJECT(graph3 = vxCreateGraph(context), VX_TYPE_GRAPH); |
| ASSERT_VX_OBJECT(vxMultiplyNode(graph3, src1_64x64, src2_32x32, scale, arg_->overflow_policy, arg_->round_policy, dst32x32), VX_TYPE_NODE); |
| EXPECT_NE_VX_STATUS(VX_SUCCESS, vxVerifyGraph(graph3)); |
| |
| ASSERT_VX_OBJECT(graph4 = vxCreateGraph(context), VX_TYPE_GRAPH); |
| ASSERT_VX_OBJECT(vxMultiplyNode(graph4, src1_64x64, src2_32x64, scale, arg_->overflow_policy, arg_->round_policy, dst32x32), VX_TYPE_NODE); |
| EXPECT_NE_VX_STATUS(VX_SUCCESS, vxVerifyGraph(graph4)); |
| |
| VX_CALL(vxReleaseImage(&src1_32x32)); |
| VX_CALL(vxReleaseImage(&src2_32x32)); |
| VX_CALL(vxReleaseImage(&src1_64x64)); |
| VX_CALL(vxReleaseImage(&src2_32x64)); |
| VX_CALL(vxReleaseImage(&dst32x32)); |
| VX_CALL(vxReleaseImage(&dst88x16)); |
| VX_CALL(vxReleaseScalar(&scale)); |
| VX_CALL(vxReleaseGraph(&graph1)); |
| VX_CALL(vxReleaseGraph(&graph2)); |
| VX_CALL(vxReleaseGraph(&graph3)); |
| VX_CALL(vxReleaseGraph(&graph4)); |
| } |
| |
| static vx_image inference_image; |
| static vx_enum inference_image_format; |
| static vx_action VX_CALLBACK inference_image_test(vx_node node) |
| { |
| vx_uint32 width = 0; |
| vx_uint32 height = 0; |
| vx_df_image format = 0; |
| |
| EXPECT_EQ_VX_STATUS(VX_SUCCESS, vxQueryImage(inference_image, VX_IMAGE_WIDTH, &width, sizeof(width))); |
| EXPECT_EQ_VX_STATUS(VX_SUCCESS, vxQueryImage(inference_image, VX_IMAGE_HEIGHT, &height, sizeof(height))); |
| EXPECT_EQ_VX_STATUS(VX_SUCCESS, vxQueryImage(inference_image, VX_IMAGE_FORMAT, &format, sizeof(format))); |
| |
| EXPECT_EQ_INT(640, width); |
| EXPECT_EQ_INT(480, height); |
| EXPECT_EQ_INT(inference_image_format, format); |
| |
| return VX_ACTION_CONTINUE; |
| } |
| |
| TEST_WITH_ARG(vxMultiply, testInference, formats_arg, MUL_INFERENCE_FORMATS(SATURATE), MUL_INFERENCE_FORMATS(WRAP)) |
| { |
| vx_image src1, src2, dst, gr; |
| vx_graph graph; |
| vx_scalar scale; |
| vx_node n, tmp; |
| vx_context context = context_->vx_context_; |
| |
| ASSERT_VX_OBJECT(graph = vxCreateGraph(context), VX_TYPE_GRAPH); |
| ASSERT_VX_OBJECT(src1 = vxCreateImage(context, 640, 480, arg_->arg1_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(src2 = vxCreateImage(context, 640, 480, arg_->arg2_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(dst = vxCreateVirtualImage(graph, 0, 0, VX_DF_IMAGE_VIRT), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(scale = vxCreateScalar(context, VX_TYPE_FLOAT32, &arg_->scale), VX_TYPE_SCALAR); |
| ASSERT_VX_OBJECT(n = vxMultiplyNode(graph, src1, src2, scale, arg_->overflow_policy, arg_->round_policy, dst), VX_TYPE_NODE); |
| |
| // grounding |
| ASSERT_VX_OBJECT(gr = vxCreateImage(context, 640, 480, VX_DF_IMAGE_S16), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(tmp = vxAddNode(graph, dst, src2, VX_CONVERT_POLICY_WRAP, gr), VX_TYPE_NODE); |
| |
| // test |
| inference_image = dst; |
| inference_image_format = arg_->result_format; |
| EXPECT_EQ_VX_STATUS(VX_SUCCESS, vxAssignNodeCallback(n, inference_image_test)); |
| ASSERT_EQ_VX_STATUS(VX_SUCCESS, vxProcessGraph(graph)); |
| |
| VX_CALL(vxReleaseNode(&n)); |
| VX_CALL(vxReleaseNode(&tmp)); |
| VX_CALL(vxReleaseImage(&src1)); |
| VX_CALL(vxReleaseImage(&src2)); |
| VX_CALL(vxReleaseImage(&dst)); |
| VX_CALL(vxReleaseImage(&gr)); |
| VX_CALL(vxReleaseScalar(&scale)); |
| VX_CALL(vxReleaseGraph(&graph)); |
| } |
| |
| TEST_WITH_ARG(vxuMultiply, testFuzzy, fuzzy_arg, MUL_FUZZY_ARGS(SATURATE), MUL_FUZZY_ARGS(WRAP)) |
| { |
| vx_image src1, src2, dst; |
| vx_float32 scale_val = arg_->scale; |
| CT_Image ref1, ref2, refdst, refdst_plus_1, vxdst; |
| vx_context context = context_->vx_context_; |
| |
| ASSERT_VX_OBJECT(src1 = vxCreateImage(context, arg_->width, arg_->height, arg_->arg1_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(src2 = vxCreateImage(context, arg_->width, arg_->height, arg_->arg2_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(dst = vxCreateImage(context, arg_->width, arg_->height, arg_->result_format), VX_TYPE_IMAGE); |
| |
| ASSERT_NO_FAILURE(ct_fill_image_random(src1, &CT()->seed_)); |
| ASSERT_NO_FAILURE(ct_fill_image_random(src2, &CT()->seed_)); |
| |
| ASSERT_EQ_VX_STATUS(VX_SUCCESS, vxuMultiply(context, src1, src2, scale_val, arg_->overflow_policy, arg_->round_policy, dst)); |
| |
| ASSERT_NO_FAILURE({ |
| ref1 = ct_image_from_vx_image(src1); |
| ref2 = ct_image_from_vx_image(src2); |
| vxdst = ct_image_from_vx_image(dst); |
| refdst = ct_allocate_image(arg_->width, arg_->height, arg_->result_format); |
| refdst_plus_1 = ct_allocate_image(arg_->width, arg_->height, arg_->result_format); |
| |
| referenceMultiply(ref1, ref2, refdst, refdst_plus_1, arg_->scale, arg_->overflow_policy); |
| }); |
| |
| if (arg_->scale == ONE_2_0) |
| ASSERT_EQ_CTIMAGE(refdst, vxdst); |
| else |
| { |
| // (|ref-v| <= 1 && |ref+1-v| <= 1) is equivalent to (v == ref || v == ref + 1) |
| if (arg_->overflow_policy == VX_CONVERT_POLICY_WRAP) |
| { |
| EXPECT_CTIMAGE_NEARWRAP(refdst, vxdst, 1, CTIMAGE_ALLOW_WRAP); |
| EXPECT_CTIMAGE_NEARWRAP(refdst_plus_1, vxdst, 1, CTIMAGE_ALLOW_WRAP); |
| } |
| else |
| { |
| EXPECT_CTIMAGE_NEAR(refdst, vxdst, 1); |
| EXPECT_CTIMAGE_NEAR(refdst_plus_1, vxdst, 1); |
| } |
| } |
| |
| // checked release vx images |
| VX_CALL(vxReleaseImage(&dst)); |
| VX_CALL(vxReleaseImage(&src1)); |
| VX_CALL(vxReleaseImage(&src2)); |
| EXPECT_EQ_PTR(NULL, dst); |
| EXPECT_EQ_PTR(NULL, src1); |
| EXPECT_EQ_PTR(NULL, src2); |
| } |
| |
| TEST_WITH_ARG(vxMultiply, testFuzzy, fuzzy_arg, MUL_FUZZY_ARGS(SATURATE), MUL_FUZZY_ARGS(WRAP)) |
| { |
| vx_image src1, src2, dst; |
| vx_graph graph; |
| vx_scalar scale = 0; |
| CT_Image ref1, ref2, refdst, refdst_plus_1, vxdst; |
| vx_context context = context_->vx_context_; |
| |
| ASSERT_VX_OBJECT(graph = vxCreateGraph(context), VX_TYPE_GRAPH); |
| ASSERT_VX_OBJECT(dst = vxCreateImage(context, arg_->width, arg_->height, arg_->result_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(scale = vxCreateScalar(context, VX_TYPE_FLOAT32, &arg_->scale), VX_TYPE_SCALAR); |
| |
| ASSERT_VX_OBJECT(src1 = vxCreateImage(context, arg_->width, arg_->height, arg_->arg1_format), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(src2 = vxCreateImage(context, arg_->width, arg_->height, arg_->arg2_format), VX_TYPE_IMAGE); |
| |
| ASSERT_NO_FAILURE(ct_fill_image_random(src1, &CT()->seed_)); |
| ASSERT_NO_FAILURE(ct_fill_image_random(src2, &CT()->seed_)); |
| |
| // build one-node graph |
| ASSERT_VX_OBJECT(vxMultiplyNode(graph, src1, src2, scale, arg_->overflow_policy, arg_->round_policy, dst), VX_TYPE_NODE); |
| |
| // run graph |
| #ifdef CT_EXECUTE_ASYNC |
| ASSERT_EQ_VX_STATUS(VX_SUCCESS, vxScheduleGraph(graph)); |
| ASSERT_EQ_VX_STATUS(VX_SUCCESS, vxWaitGraph(graph)); |
| #else |
| ASSERT_EQ_VX_STATUS(VX_SUCCESS, vxProcessGraph(graph)); |
| #endif |
| |
| ASSERT_NO_FAILURE({ |
| ref1 = ct_image_from_vx_image(src1); |
| ref2 = ct_image_from_vx_image(src2); |
| vxdst = ct_image_from_vx_image(dst); |
| refdst = ct_allocate_image(arg_->width, arg_->height, arg_->result_format); |
| refdst_plus_1 = ct_allocate_image(arg_->width, arg_->height, arg_->result_format); |
| |
| referenceMultiply(ref1, ref2, refdst, refdst_plus_1, arg_->scale, arg_->overflow_policy); |
| }); |
| |
| if (arg_->scale == ONE_2_0) |
| ASSERT_EQ_CTIMAGE(refdst, vxdst); |
| else |
| { |
| // (|ref-v| <= 1 && |ref+1-v| <= 1) is equivalent to (v == ref || v == ref + 1) |
| if (arg_->overflow_policy == VX_CONVERT_POLICY_WRAP) |
| { |
| EXPECT_CTIMAGE_NEARWRAP(refdst, vxdst, 1, CTIMAGE_ALLOW_WRAP); |
| EXPECT_CTIMAGE_NEARWRAP(refdst_plus_1, vxdst, 1, CTIMAGE_ALLOW_WRAP); |
| } |
| else |
| { |
| EXPECT_CTIMAGE_NEAR(refdst, vxdst, 1); |
| EXPECT_CTIMAGE_NEAR(refdst_plus_1, vxdst, 1); |
| } |
| } |
| |
| VX_CALL(vxReleaseImage(&src1)); |
| VX_CALL(vxReleaseImage(&src2)); |
| VX_CALL(vxReleaseImage(&dst)); |
| VX_CALL(vxReleaseScalar(&scale)); |
| VX_CALL(vxReleaseGraph(&graph)); |
| } |
| |
| TESTCASE_TESTS(vxuMultiply, DISABLED_testNegativeFormat, DISABLED_testNegativeSizes, testFuzzy) |
| TESTCASE_TESTS(vxMultiply, DISABLED_testNegativeFormat, DISABLED_testNegativeSizes, testInference, testFuzzy) |