1 /*******************************************************************************
2 * Copyright 2019-2021 Intel Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *******************************************************************************/
16 
17 #include "dnnl_test_common.hpp"
18 #include "gtest/gtest.h"
19 
20 #include <memory>
21 #include "oneapi/dnnl/dnnl_ocl.h"
22 #include "oneapi/dnnl/dnnl_ocl.hpp"
23 #include <CL/cl.h>
24 
25 namespace dnnl {
26 class ocl_stream_test_c_t : public ::testing::Test {
27 protected:
SetUp()28     void SetUp() override {
29         if (!find_ocl_device(CL_DEVICE_TYPE_GPU)) { return; }
30 
31         DNNL_CHECK(dnnl_engine_create(&eng, dnnl_gpu, 0));
32 
33         DNNL_CHECK(dnnl_ocl_interop_engine_get_context(eng, &ocl_ctx));
34         DNNL_CHECK(dnnl_ocl_interop_get_device(eng, &ocl_dev));
35     }
36 
TearDown()37     void TearDown() override {
38         if (eng) { DNNL_CHECK(dnnl_engine_destroy(eng)); }
39     }
40 
41     dnnl_engine_t eng = nullptr;
42     cl_context ocl_ctx = nullptr;
43     cl_device_id ocl_dev = nullptr;
44 };
45 
46 class ocl_stream_test_cpp_t : public ::testing::Test {
47 protected:
SetUp()48     void SetUp() override {
49         if (!find_ocl_device(CL_DEVICE_TYPE_GPU)) { return; }
50 
51         eng = engine(engine::kind::gpu, 0);
52 
53         ocl_ctx = ocl_interop::get_context(eng);
54         ocl_dev = ocl_interop::get_device(eng);
55     }
56 
57     engine eng;
58     cl_context ocl_ctx = nullptr;
59     cl_device_id ocl_dev = nullptr;
60 };
61 
TEST_F(ocl_stream_test_c_t,CreateC)62 TEST_F(ocl_stream_test_c_t, CreateC) {
63     SKIP_IF(!find_ocl_device(CL_DEVICE_TYPE_GPU),
64             "OpenCL GPU devices not found.");
65 
66     dnnl_stream_t stream;
67     DNNL_CHECK(dnnl_stream_create(&stream, eng, dnnl_stream_default_flags));
68 
69     cl_command_queue ocl_queue;
70     DNNL_CHECK(dnnl_ocl_interop_stream_get_command_queue(stream, &ocl_queue));
71 
72     cl_device_id ocl_queue_dev;
73     cl_context ocl_queue_ctx;
74     TEST_OCL_CHECK(clGetCommandQueueInfo(ocl_queue, CL_QUEUE_DEVICE,
75             sizeof(ocl_queue_dev), &ocl_queue_dev, nullptr));
76     TEST_OCL_CHECK(clGetCommandQueueInfo(ocl_queue, CL_QUEUE_CONTEXT,
77             sizeof(ocl_queue_ctx), &ocl_queue_ctx, nullptr));
78 
79     ASSERT_EQ(ocl_dev, ocl_queue_dev);
80     ASSERT_EQ(ocl_ctx, ocl_queue_ctx);
81 
82     DNNL_CHECK(dnnl_stream_destroy(stream));
83 }
84 
TEST_F(ocl_stream_test_cpp_t,CreateCpp)85 TEST_F(ocl_stream_test_cpp_t, CreateCpp) {
86     SKIP_IF(!find_ocl_device(CL_DEVICE_TYPE_GPU),
87             "OpenCL GPU devices not found.");
88 
89     stream s(eng);
90     cl_command_queue ocl_queue = ocl_interop::get_command_queue(s);
91 
92     cl_device_id ocl_queue_dev;
93     cl_context ocl_queue_ctx;
94     TEST_OCL_CHECK(clGetCommandQueueInfo(ocl_queue, CL_QUEUE_DEVICE,
95             sizeof(ocl_queue_dev), &ocl_queue_dev, nullptr));
96     TEST_OCL_CHECK(clGetCommandQueueInfo(ocl_queue, CL_QUEUE_CONTEXT,
97             sizeof(ocl_queue_ctx), &ocl_queue_ctx, nullptr));
98 
99     ASSERT_EQ(ocl_dev, ocl_queue_dev);
100     ASSERT_EQ(ocl_ctx, ocl_queue_ctx);
101 }
102 
TEST_F(ocl_stream_test_c_t,BasicInteropC)103 TEST_F(ocl_stream_test_c_t, BasicInteropC) {
104     SKIP_IF(!find_ocl_device(CL_DEVICE_TYPE_GPU),
105             "OpenCL GPU devices not found.");
106 
107     cl_int err;
108 #ifdef CL_VERSION_2_0
109     cl_command_queue interop_ocl_queue = clCreateCommandQueueWithProperties(
110             ocl_ctx, ocl_dev, nullptr, &err);
111 #else
112     cl_command_queue interop_ocl_queue
113             = clCreateCommandQueue(ocl_ctx, ocl_dev, 0, &err);
114 #endif
115     TEST_OCL_CHECK(err);
116 
117     dnnl_stream_t stream;
118     DNNL_CHECK(dnnl_ocl_interop_stream_create(&stream, eng, interop_ocl_queue));
119 
120     cl_command_queue ocl_queue;
121     DNNL_CHECK(dnnl_ocl_interop_stream_get_command_queue(stream, &ocl_queue));
122     ASSERT_EQ(ocl_queue, interop_ocl_queue);
123 
124     cl_uint ref_count;
125     TEST_OCL_CHECK(clGetCommandQueueInfo(interop_ocl_queue,
126             CL_QUEUE_REFERENCE_COUNT, sizeof(cl_uint), &ref_count, nullptr));
127     int i_ref_count = int(ref_count);
128     ASSERT_EQ(i_ref_count, 2);
129 
130     DNNL_CHECK(dnnl_stream_destroy(stream));
131 
132     TEST_OCL_CHECK(clGetCommandQueueInfo(interop_ocl_queue,
133             CL_QUEUE_REFERENCE_COUNT, sizeof(cl_uint), &ref_count, nullptr));
134     i_ref_count = int(ref_count);
135     ASSERT_EQ(i_ref_count, 1);
136 
137     TEST_OCL_CHECK(clReleaseCommandQueue(interop_ocl_queue));
138 }
139 
TEST_F(ocl_stream_test_cpp_t,BasicInteropC)140 TEST_F(ocl_stream_test_cpp_t, BasicInteropC) {
141     SKIP_IF(!find_ocl_device(CL_DEVICE_TYPE_GPU),
142             "OpenCL GPU devices not found.");
143 
144     cl_int err;
145 #ifdef CL_VERSION_2_0
146     cl_command_queue interop_ocl_queue = clCreateCommandQueueWithProperties(
147             ocl_ctx, ocl_dev, nullptr, &err);
148 #else
149     cl_command_queue interop_ocl_queue
150             = clCreateCommandQueue(ocl_ctx, ocl_dev, 0, &err);
151 #endif
152     TEST_OCL_CHECK(err);
153 
154     {
155         auto s = ocl_interop::make_stream(eng, interop_ocl_queue);
156 
157         cl_uint ref_count;
158         TEST_OCL_CHECK(clGetCommandQueueInfo(interop_ocl_queue,
159                 CL_QUEUE_REFERENCE_COUNT, sizeof(cl_uint), &ref_count,
160                 nullptr));
161         int i_ref_count = int(ref_count);
162         ASSERT_EQ(i_ref_count, 2);
163 
164         cl_command_queue ocl_queue = ocl_interop::get_command_queue(s);
165         ASSERT_EQ(ocl_queue, interop_ocl_queue);
166     }
167 
168     cl_uint ref_count;
169     TEST_OCL_CHECK(clGetCommandQueueInfo(interop_ocl_queue,
170             CL_QUEUE_REFERENCE_COUNT, sizeof(cl_uint), &ref_count, nullptr));
171     int i_ref_count = int(ref_count);
172     ASSERT_EQ(i_ref_count, 1);
173 
174     TEST_OCL_CHECK(clReleaseCommandQueue(interop_ocl_queue));
175 }
176 
TEST_F(ocl_stream_test_c_t,InteropIncompatibleQueueC)177 TEST_F(ocl_stream_test_c_t, InteropIncompatibleQueueC) {
178     SKIP_IF(!find_ocl_device(CL_DEVICE_TYPE_GPU),
179             "OpenCL GPU devices not found.");
180 
181     cl_device_id cpu_ocl_dev = find_ocl_device(CL_DEVICE_TYPE_CPU);
182     SKIP_IF(!cpu_ocl_dev, "OpenCL CPU devices not found.");
183 
184     cl_int err;
185     cl_context cpu_ocl_ctx
186             = clCreateContext(nullptr, 1, &cpu_ocl_dev, nullptr, nullptr, &err);
187     TEST_OCL_CHECK(err);
188 
189 #ifdef CL_VERSION_2_0
190     cl_command_queue cpu_ocl_queue = clCreateCommandQueueWithProperties(
191             cpu_ocl_ctx, cpu_ocl_dev, nullptr, &err);
192 #else
193     cl_command_queue cpu_ocl_queue
194             = clCreateCommandQueue(cpu_ocl_ctx, cpu_ocl_dev, 0, &err);
195 #endif
196     TEST_OCL_CHECK(err);
197 
198     dnnl_stream_t stream;
199     dnnl_status_t status
200             = dnnl_ocl_interop_stream_create(&stream, eng, cpu_ocl_queue);
201     ASSERT_EQ(status, dnnl_invalid_arguments);
202 
203     TEST_OCL_CHECK(clReleaseCommandQueue(cpu_ocl_queue));
204 }
205 
TEST_F(ocl_stream_test_cpp_t,InteropIncompatibleQueueCpp)206 TEST_F(ocl_stream_test_cpp_t, InteropIncompatibleQueueCpp) {
207     SKIP_IF(!find_ocl_device(CL_DEVICE_TYPE_GPU),
208             "OpenCL GPU devices not found.");
209 
210     cl_device_id cpu_ocl_dev = find_ocl_device(CL_DEVICE_TYPE_CPU);
211     SKIP_IF(!cpu_ocl_dev, "OpenCL CPU devices not found.");
212 
213     cl_int err;
214     cl_context cpu_ocl_ctx
215             = clCreateContext(nullptr, 1, &cpu_ocl_dev, nullptr, nullptr, &err);
216     TEST_OCL_CHECK(err);
217 
218 #ifdef CL_VERSION_2_0
219     cl_command_queue cpu_ocl_queue = clCreateCommandQueueWithProperties(
220             cpu_ocl_ctx, cpu_ocl_dev, nullptr, &err);
221 #else
222     cl_command_queue cpu_ocl_queue
223             = clCreateCommandQueue(cpu_ocl_ctx, cpu_ocl_dev, 0, &err);
224 #endif
225     TEST_OCL_CHECK(err);
226 
227     catch_expected_failures(
228             [&] { ocl_interop::make_stream(eng, cpu_ocl_queue); }, true,
229             dnnl_invalid_arguments);
230 
231     TEST_OCL_CHECK(clReleaseCommandQueue(cpu_ocl_queue));
232 }
233 
234 } // namespace dnnl
235