1 //
2 // Copyright (c) 2017-2020 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 "testBase.h"
17
18 #if !defined(_WIN32)
19 #include <unistd.h>
20 #endif
21
22 #include <atomic>
23 #include <string>
24
25 namespace {
26
27 const char *sample_async_kernel[] = {
28 "__kernel void sample_test(__global float *src, __global int *dst)\n"
29 "{\n"
30 " size_t tid = get_global_id(0);\n"
31 "\n"
32 " dst[tid] = (int)src[tid];\n"
33 "\n"
34 "}\n"
35 };
36
37 const char *sample_async_kernel_error[] = {
38 "__kernel void sample_test(__global float *src, __global int *dst)\n"
39 "{\n"
40 " size_t tid = get_global_id(0);\n"
41 "\n"
42 " dst[tid] = badcodehere;\n"
43 "\n"
44 "}\n"
45 };
46
47 // Data passed to a program completion callback
48 struct TestData
49 {
50 cl_device_id device;
51 cl_build_status expectedStatus;
52 };
53
54 std::atomic<int> callbackResult;
55
56 }
57
test_notify_build_complete(cl_program program,void * userData)58 void CL_CALLBACK test_notify_build_complete(cl_program program, void *userData)
59 {
60 TestData *data = reinterpret_cast<TestData *>(userData);
61
62 // Check user data is valid
63 if (data == nullptr)
64 {
65 log_error("ERROR: User data passed to callback was not valid!\n");
66 callbackResult = -1;
67 return;
68 }
69
70 // Get program build status
71 cl_build_status status;
72 cl_int err =
73 clGetProgramBuildInfo(program, data->device, CL_PROGRAM_BUILD_STATUS,
74 sizeof(cl_build_status), &status, NULL);
75 if (err != CL_SUCCESS)
76 {
77 log_info("ERROR: failed to get build status from callback\n");
78 callbackResult = -1;
79 return;
80 }
81
82 log_info("Program completion callback received build status %d\n", status);
83
84 // Check program build status matches expectation
85 if (status != data->expectedStatus)
86 {
87 log_info("ERROR: build status %d != expected status %d\n", status,
88 data->expectedStatus);
89 callbackResult = -1;
90 }
91 else
92 {
93 callbackResult = 1;
94 }
95 }
96
test_async_build(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)97 int test_async_build(cl_device_id deviceID, cl_context context,
98 cl_command_queue queue, int num_elements)
99 {
100 cl_int error;
101
102 struct TestDef
103 {
104 const char **source;
105 cl_build_status expectedStatus;
106 };
107
108 TestDef testDefs[] = { { sample_async_kernel, CL_BUILD_SUCCESS },
109 { sample_async_kernel_error, CL_BUILD_ERROR } };
110 for (TestDef &testDef : testDefs)
111 {
112 log_info("\nTesting program that should produce status %d\n",
113 testDef.expectedStatus);
114
115 // Create the program
116 clProgramWrapper program;
117 error = create_single_kernel_helper_create_program(context, &program, 1,
118 testDef.source);
119 test_error(error, "Unable to create program from source");
120
121 // Start an asynchronous build, registering the completion callback
122 TestData testData = { deviceID, testDef.expectedStatus };
123 callbackResult = 0;
124 error = clBuildProgram(program, 1, &deviceID, NULL,
125 test_notify_build_complete, (void *)&testData);
126 // Allow implementations to return synchronous build failures.
127 // They still need to call the callback.
128 if (!(error == CL_BUILD_PROGRAM_FAILURE
129 && testDef.expectedStatus == CL_BUILD_ERROR))
130 test_error(error, "Unable to start build");
131
132 // Wait for callback to fire
133 int timeout = 20;
134 while (callbackResult == 0)
135 {
136 if (timeout < 0)
137 {
138 log_error("Timeout while waiting for callback to fire.\n\n");
139 return -1;
140 }
141
142 log_info(" -- still waiting for callback...\n");
143 sleep(1);
144 timeout--;
145 }
146
147 // Check the callback result
148 if (callbackResult == 1)
149 {
150 log_error("Test passed.\n\n");
151 }
152 else
153 {
154 log_error("Async build callback indicated test failure.\n\n");
155 return -1;
156 }
157 }
158
159 return 0;
160 }
161