1 /*
2  * Copyright (C) 2018-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #include "shared/source/built_ins/built_ins.h"
9 #include "shared/source/compiler_interface/compiler_interface.h"
10 #include "shared/source/device/device.h"
11 
12 #include "opencl/source/built_ins/built_in_ops_vme.h"
13 #include "opencl/source/built_ins/vme_builtin.h"
14 #include "opencl/source/context/context.h"
15 #include "opencl/source/helpers/base_object.h"
16 #include "opencl/source/kernel/kernel.h"
17 #include "opencl/source/program/program.h"
18 #include "opencl/test/unit_test/fixtures/run_kernel_fixture.h"
19 #include "opencl/test/unit_test/mocks/mock_cl_device.h"
20 
21 #include "cl_api_tests.h"
22 
23 using namespace NEO;
24 
25 typedef api_tests clCreateProgramWithBuiltInKernelsTests;
26 
27 struct clCreateProgramWithBuiltInVmeKernelsTests : clCreateProgramWithBuiltInKernelsTests {
SetUpclCreateProgramWithBuiltInVmeKernelsTests28     void SetUp() override {
29         clCreateProgramWithBuiltInKernelsTests::SetUp();
30         if (!castToObject<ClDevice>(testedClDevice)->getHardwareInfo().capabilityTable.supportsVme) {
31             GTEST_SKIP();
32         }
33 
34         pClDevice = pContext->getDevice(0);
35     }
36 
37     ClDevice *pClDevice;
38 };
39 
40 namespace ULT {
41 
TEST_F(clCreateProgramWithBuiltInKernelsTests,GivenInvalidContextWhenCreatingProgramWithBuiltInKernelsThenInvalidContextErrorIsReturned)42 TEST_F(clCreateProgramWithBuiltInKernelsTests, GivenInvalidContextWhenCreatingProgramWithBuiltInKernelsThenInvalidContextErrorIsReturned) {
43     cl_int retVal = CL_SUCCESS;
44     auto program = clCreateProgramWithBuiltInKernels(
45         nullptr, // context
46         1,       // num_devices
47         nullptr, // device_list
48         nullptr, // kernel_names
49         &retVal);
50     EXPECT_EQ(nullptr, program);
51     EXPECT_EQ(CL_INVALID_CONTEXT, retVal);
52 }
53 
TEST_F(clCreateProgramWithBuiltInKernelsTests,GivenNoKernelsWhenCreatingProgramWithBuiltInKernelsThenInvalidValueErrorIsReturned)54 TEST_F(clCreateProgramWithBuiltInKernelsTests, GivenNoKernelsWhenCreatingProgramWithBuiltInKernelsThenInvalidValueErrorIsReturned) {
55     cl_int retVal = CL_SUCCESS;
56     auto program = clCreateProgramWithBuiltInKernels(
57         pContext,        // context
58         1,               // num_devices
59         &testedClDevice, // device_list
60         "",              // kernel_names
61         &retVal);
62     EXPECT_EQ(nullptr, program);
63     EXPECT_EQ(CL_INVALID_VALUE, retVal);
64 }
65 
TEST_F(clCreateProgramWithBuiltInKernelsTests,GivenNoDeviceWhenCreatingProgramWithBuiltInKernelsThenInvalidValueErrorIsReturned)66 TEST_F(clCreateProgramWithBuiltInKernelsTests, GivenNoDeviceWhenCreatingProgramWithBuiltInKernelsThenInvalidValueErrorIsReturned) {
67     cl_int retVal = CL_SUCCESS;
68     auto program = clCreateProgramWithBuiltInKernels(
69         pContext,        // context
70         0,               // num_devices
71         &testedClDevice, // device_list
72         "",              // kernel_names
73         &retVal);
74     EXPECT_EQ(nullptr, program);
75     EXPECT_EQ(CL_INVALID_VALUE, retVal);
76 }
77 
TEST_F(clCreateProgramWithBuiltInKernelsTests,GivenNoKernelsAndNoReturnWhenCreatingProgramWithBuiltInKernelsThenProgramIsNotCreated)78 TEST_F(clCreateProgramWithBuiltInKernelsTests, GivenNoKernelsAndNoReturnWhenCreatingProgramWithBuiltInKernelsThenProgramIsNotCreated) {
79     auto program = clCreateProgramWithBuiltInKernels(
80         pContext,        // context
81         1,               // num_devices
82         &testedClDevice, // device_list
83         "",              // kernel_names
84         nullptr);
85     EXPECT_EQ(nullptr, program);
86 }
87 
TEST_F(clCreateProgramWithBuiltInVmeKernelsTests,GivenDeviceNotAssociatedWithContextWhenCreatingProgramWithBuiltInThenInvalidDeviceErrorIsReturned)88 TEST_F(clCreateProgramWithBuiltInVmeKernelsTests, GivenDeviceNotAssociatedWithContextWhenCreatingProgramWithBuiltInThenInvalidDeviceErrorIsReturned) {
89     cl_program pProgram = nullptr;
90 
91     const char *kernelNamesString = {
92         "block_advanced_motion_estimate_bidirectional_check_intel;"
93         "block_motion_estimate_intel;"
94         "block_advanced_motion_estimate_check_intel;"};
95 
96     MockClDevice invalidDevice(new MockDevice());
97 
98     cl_device_id devicesForProgram[] = {&invalidDevice};
99 
100     pProgram = clCreateProgramWithBuiltInKernels(
101         pContext,
102         1,
103         devicesForProgram,
104         kernelNamesString,
105         &retVal);
106     EXPECT_EQ(CL_INVALID_DEVICE, retVal);
107     EXPECT_EQ(nullptr, pProgram);
108 
109     retVal = CL_INVALID_PROGRAM;
110     devicesForProgram[0] = nullptr;
111 
112     pProgram = clCreateProgramWithBuiltInKernels(
113         pContext,
114         1,
115         devicesForProgram,
116         kernelNamesString,
117         &retVal);
118     EXPECT_EQ(CL_INVALID_DEVICE, retVal);
119     EXPECT_EQ(nullptr, pProgram);
120 }
121 
TEST_F(clCreateProgramWithBuiltInVmeKernelsTests,GivenValidMediaKernelsWhenCreatingProgramWithBuiltInKernelsThenProgramIsSuccessfullyCreated)122 TEST_F(clCreateProgramWithBuiltInVmeKernelsTests, GivenValidMediaKernelsWhenCreatingProgramWithBuiltInKernelsThenProgramIsSuccessfullyCreated) {
123     cl_int retVal = CL_SUCCESS;
124 
125     overwriteBuiltInBinaryName("media_kernels_frontend");
126 
127     const char *kernelNamesString = {
128         "block_advanced_motion_estimate_bidirectional_check_intel;"
129         "block_motion_estimate_intel;"
130         "block_advanced_motion_estimate_check_intel;"};
131 
132     const char *kernelNames[] = {
133         "block_motion_estimate_intel",
134         "block_advanced_motion_estimate_check_intel",
135         "block_advanced_motion_estimate_bidirectional_check_intel",
136     };
137 
138     cl_program program = clCreateProgramWithBuiltInKernels(
139         pContext,          // context
140         1,                 // num_devices
141         &testedClDevice,   // device_list
142         kernelNamesString, // kernel_names
143         &retVal);
144 
145     restoreBuiltInBinaryName();
146     EXPECT_NE(nullptr, program);
147     EXPECT_EQ(CL_SUCCESS, retVal);
148 
149     for (auto &kernelName : kernelNames) {
150         cl_kernel kernel = clCreateKernel(
151             program,
152             kernelName,
153             &retVal);
154         ASSERT_EQ(CL_SUCCESS, retVal);
155         ASSERT_NE(nullptr, kernel);
156 
157         retVal = clReleaseKernel(kernel);
158         EXPECT_EQ(CL_SUCCESS, retVal);
159     }
160 
161     retVal = clReleaseProgram(program);
162     EXPECT_EQ(CL_SUCCESS, retVal);
163 }
164 
TEST_F(clCreateProgramWithBuiltInVmeKernelsTests,GivenValidMediaKernelsWithOptionsWhenCreatingProgramWithBuiltInKernelsThenProgramIsSuccessfullyCreatedWithThoseOptions)165 TEST_F(clCreateProgramWithBuiltInVmeKernelsTests, GivenValidMediaKernelsWithOptionsWhenCreatingProgramWithBuiltInKernelsThenProgramIsSuccessfullyCreatedWithThoseOptions) {
166     cl_int retVal = CL_SUCCESS;
167 
168     overwriteBuiltInBinaryName("media_kernels_frontend");
169 
170     const char *kernelNamesString = {
171         "block_motion_estimate_intel;"};
172 
173     cl_program program = clCreateProgramWithBuiltInKernels(
174         pContext,          // context
175         1,                 // num_devices
176         &testedClDevice,   // device_list
177         kernelNamesString, // kernel_names
178         &retVal);
179 
180     restoreBuiltInBinaryName();
181 
182     auto neoProgram = castToObject<Program>(program);
183     auto builtinOptions = neoProgram->getOptions();
184     auto it = builtinOptions.find("HW_NULL_CHECK");
185     EXPECT_EQ(std::string::npos, it);
186 
187     clReleaseProgram(program);
188 }
189 
TEST_F(clCreateProgramWithBuiltInVmeKernelsTests,GivenVmeBlockMotionEstimateKernelWhenCreatingProgramWithBuiltInKernelsThenCorrectDispatchBuilderAndFrontendKernelIsCreated)190 TEST_F(clCreateProgramWithBuiltInVmeKernelsTests, GivenVmeBlockMotionEstimateKernelWhenCreatingProgramWithBuiltInKernelsThenCorrectDispatchBuilderAndFrontendKernelIsCreated) {
191     cl_int retVal = CL_SUCCESS;
192 
193     overwriteBuiltInBinaryName("media_kernels_backend");
194     Vme::getBuiltinDispatchInfoBuilder(EBuiltInOps::VmeBlockMotionEstimateIntel, *pClDevice);
195     restoreBuiltInBinaryName();
196 
197     overwriteBuiltInBinaryName("media_kernels_frontend");
198 
199     const char *kernelNamesString = {
200         "block_motion_estimate_intel;"};
201 
202     cl_program program = clCreateProgramWithBuiltInKernels(
203         pContext,          // context
204         1,                 // num_devices
205         &testedClDevice,   // device_list
206         kernelNamesString, // kernel_names
207         &retVal);
208     restoreBuiltInBinaryName();
209 
210     cl_kernel kernel = clCreateKernel(
211         program,
212         "block_motion_estimate_intel",
213         &retVal);
214 
215     auto pMultiDeviceKernel = castToObject<MultiDeviceKernel>(kernel);
216     auto kernNeo = pMultiDeviceKernel->getKernel(testedRootDeviceIndex);
217     EXPECT_NE(nullptr, kernNeo->getKernelInfo().builtinDispatchBuilder);
218     EXPECT_EQ(6U, kernNeo->getKernelArgsNumber());
219 
220     auto &vmeBuilder = Vme::getBuiltinDispatchInfoBuilder(EBuiltInOps::VmeBlockMotionEstimateIntel, *pClDevice);
221     EXPECT_EQ(&vmeBuilder, kernNeo->getKernelInfo().builtinDispatchBuilder);
222 
223     clReleaseKernel(kernel);
224     clReleaseProgram(program);
225 }
226 
TEST_F(clCreateProgramWithBuiltInVmeKernelsTests,GivenVmeBlockAdvancedMotionEstimateKernelWhenCreatingProgramWithBuiltInKernelsThenCorrectDispatchBuilderAndFrontendKernelIsCreated)227 TEST_F(clCreateProgramWithBuiltInVmeKernelsTests, GivenVmeBlockAdvancedMotionEstimateKernelWhenCreatingProgramWithBuiltInKernelsThenCorrectDispatchBuilderAndFrontendKernelIsCreated) {
228     cl_int retVal = CL_SUCCESS;
229 
230     overwriteBuiltInBinaryName("media_kernels_backend");
231     Vme::getBuiltinDispatchInfoBuilder(EBuiltInOps::VmeBlockAdvancedMotionEstimateCheckIntel, *pClDevice);
232     restoreBuiltInBinaryName();
233 
234     overwriteBuiltInBinaryName("media_kernels_frontend");
235 
236     const char *kernelNamesString = {
237         "block_advanced_motion_estimate_check_intel;"};
238 
239     cl_program program = clCreateProgramWithBuiltInKernels(
240         pContext,          // context
241         1,                 // num_devices
242         &testedClDevice,   // device_list
243         kernelNamesString, // kernel_names
244         &retVal);
245     restoreBuiltInBinaryName();
246 
247     cl_kernel kernel = clCreateKernel(
248         program,
249         "block_advanced_motion_estimate_check_intel",
250         &retVal);
251 
252     auto pMultiDeviceKernel = castToObject<MultiDeviceKernel>(kernel);
253     auto kernNeo = pMultiDeviceKernel->getKernel(testedRootDeviceIndex);
254     EXPECT_NE(nullptr, kernNeo->getKernelInfo().builtinDispatchBuilder);
255     EXPECT_EQ(15U, kernNeo->getKernelArgsNumber());
256 
257     auto &vmeBuilder = Vme::getBuiltinDispatchInfoBuilder(EBuiltInOps::VmeBlockAdvancedMotionEstimateCheckIntel, *pClDevice);
258     EXPECT_EQ(&vmeBuilder, kernNeo->getKernelInfo().builtinDispatchBuilder);
259 
260     clReleaseKernel(kernel);
261     clReleaseProgram(program);
262 }
263 
TEST_F(clCreateProgramWithBuiltInVmeKernelsTests,GivenVmeBlockAdvancedMotionEstimateBidirectionalCheckKernelWhenCreatingProgramWithBuiltInKernelsThenCorrectDispatchBuilderAndFrontendKernelIsCreated)264 TEST_F(clCreateProgramWithBuiltInVmeKernelsTests, GivenVmeBlockAdvancedMotionEstimateBidirectionalCheckKernelWhenCreatingProgramWithBuiltInKernelsThenCorrectDispatchBuilderAndFrontendKernelIsCreated) {
265     cl_int retVal = CL_SUCCESS;
266 
267     overwriteBuiltInBinaryName("media_kernels_backend");
268     Vme::getBuiltinDispatchInfoBuilder(EBuiltInOps::VmeBlockAdvancedMotionEstimateBidirectionalCheckIntel, *pClDevice);
269     restoreBuiltInBinaryName();
270 
271     overwriteBuiltInBinaryName("media_kernels_frontend");
272 
273     const char *kernelNamesString = {
274         "block_advanced_motion_estimate_bidirectional_check_intel;"};
275 
276     cl_program program = clCreateProgramWithBuiltInKernels(
277         pContext,          // context
278         1,                 // num_devices
279         &testedClDevice,   // device_list
280         kernelNamesString, // kernel_names
281         &retVal);
282     restoreBuiltInBinaryName();
283 
284     cl_kernel kernel = clCreateKernel(
285         program,
286         "block_advanced_motion_estimate_bidirectional_check_intel",
287         &retVal);
288 
289     auto pMultiDeviceKernel = castToObject<MultiDeviceKernel>(kernel);
290     auto kernNeo = pMultiDeviceKernel->getKernel(testedRootDeviceIndex);
291     EXPECT_NE(nullptr, kernNeo->getKernelInfo().builtinDispatchBuilder);
292     EXPECT_EQ(20U, kernNeo->getKernelArgsNumber());
293 
294     auto ctxNeo = castToObject<Context>(pContext);
295     auto &vmeBuilder = Vme::getBuiltinDispatchInfoBuilder(EBuiltInOps::VmeBlockAdvancedMotionEstimateBidirectionalCheckIntel, *ctxNeo->getDevice(0));
296     EXPECT_EQ(&vmeBuilder, kernNeo->getKernelInfo().builtinDispatchBuilder);
297 
298     clReleaseKernel(kernel);
299     clReleaseProgram(program);
300 }
301 } // namespace ULT
302