1 //
2 // Copyright (c) 2017 The Khronos Group Inc.
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 #include "utils.h"
17
interop_user_sync(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements,unsigned int width,unsigned int height,TContextFuncType functionCreate,cl_dx9_media_adapter_type_khr adapterType,TSurfaceFormat surfaceFormat,TSharedHandleType sharedHandle,cl_bool userSync)18 int interop_user_sync(cl_device_id deviceID, cl_context context,
19 cl_command_queue queue, int num_elements,
20 unsigned int width, unsigned int height,
21 TContextFuncType functionCreate,
22 cl_dx9_media_adapter_type_khr adapterType,
23 TSurfaceFormat surfaceFormat,
24 TSharedHandleType sharedHandle, cl_bool userSync)
25 {
26 CResult result;
27
28 // create device
29 std::auto_ptr<CDeviceWrapper> deviceWrapper;
30 if (!DeviceCreate(adapterType, deviceWrapper))
31 {
32 result.ResultSub(CResult::TEST_ERROR);
33 return result.Result();
34 }
35
36 // generate input data
37 std::vector<cl_uchar> bufferIn(width * height * 3 / 2, 0);
38 if (!YUVGenerate(surfaceFormat, bufferIn, width, height, 0, 255))
39 {
40 result.ResultSub(CResult::TEST_ERROR);
41 return result.Result();
42 }
43
44 while (deviceWrapper->AdapterNext())
45 {
46 cl_int error;
47 // check if the test can be run on the adapter
48 if (CL_SUCCESS
49 != (error = deviceExistForCLTest(gPlatformIDdetected, adapterType,
50 deviceWrapper->Device(), result,
51 sharedHandle)))
52 {
53 return result.Result();
54 }
55
56 if (surfaceFormat != SURFACE_FORMAT_NV12
57 && !SurfaceFormatCheck(adapterType, *deviceWrapper, surfaceFormat))
58 {
59 std::string sharedHandleStr =
60 (sharedHandle == SHARED_HANDLE_ENABLED) ? "yes" : "no";
61 std::string syncStr = (userSync == CL_TRUE) ? "yes" : "no";
62 std::string formatStr;
63 std::string adapterStr;
64 SurfaceFormatToString(surfaceFormat, formatStr);
65 AdapterToString(adapterType, adapterStr);
66 log_info("Skipping test case, image format is not supported by a "
67 "device (adapter type: %s, format: %s, shared handle: %s, "
68 "user sync: %s)\n",
69 adapterStr.c_str(), formatStr.c_str(),
70 sharedHandleStr.c_str(), syncStr.c_str());
71 return result.Result();
72 }
73
74 void *objectSharedHandle = 0;
75 std::auto_ptr<CSurfaceWrapper> surface;
76 if (!MediaSurfaceCreate(
77 adapterType, width, height, surfaceFormat, *deviceWrapper,
78 surface, (sharedHandle == SHARED_HANDLE_ENABLED) ? true : false,
79 &objectSharedHandle))
80 {
81 log_error("Media surface creation failed for %i adapter\n",
82 deviceWrapper->AdapterIdx());
83 result.ResultSub(CResult::TEST_ERROR);
84 return result.Result();
85 }
86
87 cl_context_properties contextProperties[] = {
88 CL_CONTEXT_PLATFORM,
89 (cl_context_properties)gPlatformIDdetected,
90 AdapterTypeToContextInfo(adapterType),
91 (cl_context_properties)deviceWrapper->Device(),
92 CL_CONTEXT_INTEROP_USER_SYNC,
93 userSync,
94 0,
95 };
96
97
98 clContextWrapper ctx;
99 switch (functionCreate)
100 {
101 case CONTEXT_CREATE_DEFAULT:
102 ctx = clCreateContext(&contextProperties[0], 1,
103 &gDeviceIDdetected, NULL, NULL, &error);
104 break;
105 case CONTEXT_CREATE_FROM_TYPE:
106 ctx = clCreateContextFromType(&contextProperties[0],
107 gDeviceTypeSelected, NULL, NULL,
108 &error);
109 break;
110 default:
111 log_error("Unknown context creation function enum\n");
112 result.ResultSub(CResult::TEST_ERROR);
113 return result.Result();
114 break;
115 }
116
117 if (error != CL_SUCCESS)
118 {
119 std::string functionName;
120 FunctionContextCreateToString(functionCreate, functionName);
121 log_error("%s failed: %s\n", functionName.c_str(),
122 IGetErrorString(error));
123 result.ResultSub(CResult::TEST_FAIL);
124 return result.Result();
125 }
126
127 if (!YUVSurfaceSet(surfaceFormat, surface, bufferIn, width, height))
128 {
129 result.ResultSub(CResult::TEST_ERROR);
130 return result.Result();
131 }
132
133 #if defined(_WIN32)
134 cl_dx9_surface_info_khr surfaceInfo;
135 surfaceInfo.resource =
136 *(static_cast<CD3D9SurfaceWrapper *>(surface.get()));
137 surfaceInfo.shared_handle = objectSharedHandle;
138 #else
139 void *surfaceInfo = 0;
140 return TEST_NOT_IMPLEMENTED;
141 #endif
142
143 std::vector<cl_mem> memObjList;
144 unsigned int planesNum = PlanesNum(surfaceFormat);
145 std::vector<clMemWrapper> planesList(planesNum);
146 for (unsigned int planeIdx = 0; planeIdx < planesNum; ++planeIdx)
147 {
148 planesList[planeIdx] = clCreateFromDX9MediaSurfaceKHR(
149 ctx, CL_MEM_READ_WRITE, adapterType, &surfaceInfo, planeIdx,
150 &error);
151 if (error != CL_SUCCESS)
152 {
153 log_error(
154 "clCreateFromDX9MediaSurfaceKHR failed for plane %i: %s\n",
155 planeIdx, IGetErrorString(error));
156 result.ResultSub(CResult::TEST_FAIL);
157 return result.Result();
158 }
159 memObjList.push_back(planesList[planeIdx]);
160 }
161
162 clCommandQueueWrapper cmdQueue = clCreateCommandQueueWithProperties(
163 ctx, gDeviceIDdetected, 0, &error);
164 if (error != CL_SUCCESS)
165 {
166 log_error("Unable to create command queue: %s\n",
167 IGetErrorString(error));
168 result.ResultSub(CResult::TEST_FAIL);
169 return result.Result();
170 }
171
172 if (!ImageInfoVerify(adapterType, memObjList, width, height, surface,
173 objectSharedHandle))
174 {
175 log_error("Image info verification failed\n");
176 result.ResultSub(CResult::TEST_FAIL);
177 }
178
179 if (userSync == CL_TRUE)
180 {
181 #if defined(_WIN32)
182 IDirect3DQuery9 *eventQuery = NULL;
183 switch (adapterType)
184 {
185 case CL_ADAPTER_D3D9_KHR: {
186 LPDIRECT3DDEVICE9 device =
187 (LPDIRECT3DDEVICE9)deviceWrapper->Device();
188 device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
189 eventQuery->Issue(D3DISSUE_END);
190
191 while (S_FALSE
192 == eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH))
193 ;
194 }
195 break;
196 case CL_ADAPTER_D3D9EX_KHR: {
197 LPDIRECT3DDEVICE9EX device =
198 (LPDIRECT3DDEVICE9EX)deviceWrapper->Device();
199 device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
200 eventQuery->Issue(D3DISSUE_END);
201
202 while (S_FALSE
203 == eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH))
204 ;
205 }
206 break;
207 case CL_ADAPTER_DXVA_KHR: {
208 CDXVAWrapper *DXVADevice =
209 dynamic_cast<CDXVAWrapper *>(&(*deviceWrapper));
210 LPDIRECT3DDEVICE9EX device =
211 (LPDIRECT3DDEVICE9EX)(DXVADevice->D3D9()).Device();
212 device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
213 eventQuery->Issue(D3DISSUE_END);
214
215 while (S_FALSE
216 == eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH))
217 ;
218 }
219 break;
220 default:
221 log_error("Unknown adapter type\n");
222 return false;
223 break;
224 }
225 if (eventQuery)
226 {
227 eventQuery->Release();
228 }
229 #else
230 return TEST_NOT_IMPLEMENTED;
231 #endif
232 }
233
234 error = clEnqueueAcquireDX9MediaSurfacesKHR(
235 cmdQueue, static_cast<cl_uint>(memObjList.size()),
236 &memObjList.at(0), 0, NULL, NULL);
237 if (error != CL_SUCCESS)
238 {
239 log_error("clEnqueueAcquireDX9MediaSurfacesKHR failed: %s\n",
240 IGetErrorString(error));
241 result.ResultSub(CResult::TEST_FAIL);
242 return result.Result();
243 }
244
245 size_t origin[3] = { 0, 0, 0 };
246 size_t offset = 0;
247 size_t frameSize = width * height * 3 / 2;
248 std::vector<cl_uchar> out(frameSize, 0);
249 for (size_t i = 0; i < memObjList.size(); ++i)
250 {
251 size_t planeWidth = (i == 0) ? width : width / 2;
252 size_t planeHeight = (i == 0) ? height : height / 2;
253 size_t regionPlane[3] = { planeWidth, planeHeight, 1 };
254
255 error =
256 clEnqueueReadImage(cmdQueue, memObjList.at(i), CL_TRUE, origin,
257 regionPlane, 0, 0, &out.at(offset), 0, 0, 0);
258 if (error != CL_SUCCESS)
259 {
260 log_error("clEnqueueReadImage failed: %s\n",
261 IGetErrorString(error));
262 result.ResultSub(CResult::TEST_FAIL);
263 }
264
265 offset += planeWidth * planeHeight;
266 }
267
268 if (!YUVCompare(surfaceFormat, out, bufferIn, width, height))
269 {
270 log_error("OCL object verification failed - clEnqueueReadImage\n");
271 result.ResultSub(CResult::TEST_FAIL);
272 }
273
274 error = clEnqueueReleaseDX9MediaSurfacesKHR(
275 cmdQueue, static_cast<cl_uint>(memObjList.size()),
276 &memObjList.at(0), 0, NULL, NULL);
277 if (error != CL_SUCCESS)
278 {
279 log_error("clEnqueueReleaseDX9MediaSurfacesKHR failed: %s\n",
280 IGetErrorString(error));
281 result.ResultSub(CResult::TEST_FAIL);
282 }
283
284 if (userSync == CL_TRUE)
285 {
286 error = clFinish(cmdQueue);
287 if (error != CL_SUCCESS)
288 {
289 log_error("clFinish failed: %s\n", IGetErrorString(error));
290 result.ResultSub(CResult::TEST_FAIL);
291 }
292 }
293
294 // shared object verification
295 std::vector<cl_uchar> bufferOut(frameSize, 0);
296 if (!YUVSurfaceGet(surfaceFormat, surface, bufferOut, width, height))
297 {
298 result.ResultSub(CResult::TEST_FAIL);
299 return result.Result();
300 }
301
302 if (!YUVCompare(surfaceFormat, bufferOut, bufferIn, width, height))
303 {
304 log_error("Media surface is different than expected\n");
305 result.ResultSub(CResult::TEST_FAIL);
306 }
307 }
308
309 if (deviceWrapper->Status() != DEVICE_PASS)
310 {
311 std::string adapterName;
312 AdapterToString(adapterType, adapterName);
313
314 if (deviceWrapper->Status() == DEVICE_FAIL)
315 {
316 log_error("%s init failed\n", adapterName.c_str());
317 result.ResultSub(CResult::TEST_FAIL);
318 }
319 else
320 {
321 log_error("%s init incomplete due to unsupported device\n",
322 adapterName.c_str());
323 result.ResultSub(CResult::TEST_NOTSUPPORTED);
324 }
325 }
326
327 return result.Result();
328 }
329
test_interop_user_sync(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)330 int test_interop_user_sync(cl_device_id deviceID, cl_context context,
331 cl_command_queue queue, int num_elements)
332 {
333 const unsigned int WIDTH = 256;
334 const unsigned int HEIGHT = 256;
335
336 std::vector<cl_dx9_media_adapter_type_khr> adapters;
337 #if defined(_WIN32)
338 adapters.push_back(CL_ADAPTER_D3D9_KHR);
339 adapters.push_back(CL_ADAPTER_D3D9EX_KHR);
340 adapters.push_back(CL_ADAPTER_DXVA_KHR);
341 #else
342 return TEST_NOT_IMPLEMENTED;
343 #endif
344
345 std::vector<TContextFuncType> contextFuncs;
346 contextFuncs.push_back(CONTEXT_CREATE_DEFAULT);
347 contextFuncs.push_back(CONTEXT_CREATE_FROM_TYPE);
348
349 std::vector<TSurfaceFormat> formats;
350 formats.push_back(SURFACE_FORMAT_NV12);
351 formats.push_back(SURFACE_FORMAT_YV12);
352
353 std::vector<TSharedHandleType> sharedHandleTypes;
354 sharedHandleTypes.push_back(SHARED_HANDLE_DISABLED);
355 sharedHandleTypes.push_back(SHARED_HANDLE_ENABLED);
356
357 std::vector<cl_bool> sync;
358 sync.push_back(CL_FALSE);
359 sync.push_back(CL_TRUE);
360
361 CResult result;
362 for (size_t adapterIdx = 0; adapterIdx < adapters.size(); ++adapterIdx)
363 {
364 // iteration through all create context functions
365 for (size_t contextFuncIdx = 0; contextFuncIdx < contextFuncs.size();
366 ++contextFuncIdx)
367 {
368 // iteration through YUV formats
369 for (size_t formatIdx = 0; formatIdx < formats.size(); ++formatIdx)
370 {
371 // shared handle enabled or disabled
372 for (size_t sharedHandleIdx = 0;
373 sharedHandleIdx < sharedHandleTypes.size();
374 ++sharedHandleIdx)
375 {
376 // user sync interop disabled or enabled
377 for (size_t syncIdx = 0; syncIdx < sync.size(); ++syncIdx)
378 {
379 if (adapters[adapterIdx] == CL_ADAPTER_D3D9_KHR
380 && sharedHandleTypes[sharedHandleIdx]
381 == SHARED_HANDLE_ENABLED)
382 continue;
383
384 if (interop_user_sync(
385 deviceID, context, queue, num_elements, WIDTH,
386 HEIGHT, contextFuncs[contextFuncIdx],
387 adapters[adapterIdx], formats[formatIdx],
388 sharedHandleTypes[sharedHandleIdx],
389 sync[syncIdx])
390 != 0)
391 {
392 std::string syncStr = (sync[syncIdx] == CL_TRUE)
393 ? "user sync enabled"
394 : "user sync disabled";
395 std::string sharedHandle =
396 (sharedHandleTypes[sharedHandleIdx]
397 == SHARED_HANDLE_ENABLED)
398 ? "shared handle"
399 : "no shared handle";
400 std::string adapterStr;
401 std::string formatStr;
402 SurfaceFormatToString(formats[formatIdx],
403 formatStr);
404 AdapterToString(adapters[adapterIdx], adapterStr);
405
406 log_error("\nTest case - clCreateContext (%s, %s, "
407 "%s, %s) failed\n\n",
408 adapterStr.c_str(), formatStr.c_str(),
409 sharedHandle.c_str(), syncStr.c_str());
410 result.ResultSub(CResult::TEST_FAIL);
411 }
412 }
413 }
414 }
415 }
416 }
417
418 return result.Result();
419 }
420