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 "testBase.h"
17 #include "action_classes.h"
18 
19 
20 extern const char *IGetStatusString( cl_int status );
21 
22 #define PRINT_OPS 0
23 
test_waitlist(cl_device_id device,cl_context context,cl_command_queue queue,Action * actionToTest,bool multiple)24 int test_waitlist( cl_device_id device, cl_context context, cl_command_queue queue, Action *actionToTest, bool multiple )
25 {
26     NDRangeKernelAction    actions[ 2 ];
27     clEventWrapper events[ 3 ];
28     cl_int status[ 3 ];
29     cl_int error;
30 
31   if (multiple)
32     log_info("\tExecuting reference event 0, then reference event 1 with reference event 0 in its waitlist, then test event 2 with reference events 0 and 1 in its waitlist.\n");
33   else
34     log_info("\tExecuting reference event 0, then test event 2 with reference event 0 in its waitlist.\n");
35 
36     // Set up the first base action to wait against
37     error = actions[ 0 ].Setup( device, context, queue );
38     test_error( error, "Unable to setup base event to wait against" );
39 
40     if( multiple )
41     {
42         // Set up a second event to wait against
43         error = actions[ 1 ].Setup( device, context, queue );
44         test_error( error, "Unable to setup second base event to wait against" );
45     }
46 
47     // Now set up the actual action to test
48     error = actionToTest->Setup( device, context, queue );
49     test_error( error, "Unable to set up test event" );
50 
51     // Execute all events now
52   if (PRINT_OPS) log_info("\tExecuting action 0...\n");
53     error = actions[ 0 ].Execute( queue, 0, NULL, &events[ 0 ] );
54     test_error( error, "Unable to execute first event" );
55 
56     if( multiple )
57     {
58     if (PRINT_OPS) log_info("\tExecuting action 1...\n");
59         error = actions[ 1 ].Execute( queue, 1, &events[0], &events[ 1 ] );
60         test_error( error, "Unable to execute second event" );
61     }
62 
63     // Sanity check
64   if( multiple ) {
65     if (PRINT_OPS) log_info("\tChecking status of action 1...\n");
66         error = clGetEventInfo( events[ 1 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 1 ] ), &status[ 1 ], NULL );
67     test_error( error, "Unable to get event status" );
68   }
69   if (PRINT_OPS) log_info("\tChecking status of action 0...\n");
70     error = clGetEventInfo( events[ 0 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 0 ] ), &status[ 0 ], NULL );
71   test_error( error, "Unable to get event status" );
72 
73   log_info("\t\tEvent status after starting reference events: reference event 0: %s, reference event 1: %s, test event 2: %s.\n",
74            IGetStatusString( status[ 0 ] ), (multiple ? IGetStatusString( status[ 1 ] ) : "N/A"), "N/A");
75 
76     if( ( status[ 0 ] == CL_COMPLETE ) || ( multiple && status[ 1 ] == CL_COMPLETE ) )
77     {
78         log_info( "WARNING: Reference event(s) already completed before we could execute test event! Possible that the reference event blocked (implicitly passing)\n" );
79         return 0;
80     }
81 
82   if (PRINT_OPS) log_info("\tExecuting action to test...\n");
83     error = actionToTest->Execute( queue, ( multiple ) ? 2 : 1, &events[ 0 ], &events[ 2 ] );
84     test_error( error, "Unable to execute test event" );
85 
86     // Hopefully, the first event is still running
87   if (PRINT_OPS) log_info("\tChecking status of action to test 2...\n");
88     error = clGetEventInfo( events[ 2 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 2 ] ), &status[ 2 ], NULL );
89     test_error( error, "Unable to get event status" );
90   if( multiple ) {
91     if (PRINT_OPS) log_info("\tChecking status of action 1...\n");
92         error = clGetEventInfo( events[ 1 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 1 ] ), &status[ 1 ], NULL );
93     test_error( error, "Unable to get event status" );
94   }
95   if (PRINT_OPS) log_info("\tChecking status of action 0...\n");
96     error = clGetEventInfo( events[ 0 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 0 ] ), &status[ 0 ], NULL );
97   test_error( error, "Unable to get event status" );
98 
99   log_info("\t\tEvent status after starting test event: reference event 0: %s, reference event 1: %s, test event 2: %s.\n",
100            IGetStatusString( status[ 0 ] ), (multiple ? IGetStatusString( status[ 1 ] ) : "N/A"), IGetStatusString( status[ 2 ] ));
101 
102     if( multiple )
103     {
104         if( status[ 0 ] == CL_COMPLETE && status[ 1 ] == CL_COMPLETE )
105         {
106             log_info( "WARNING: Both events completed, so unable to test further (implicitly passing).\n" );
107             clFinish( queue );
108             return 0;
109         }
110 
111     if(status[1] == CL_COMPLETE && status[0] != CL_COMPLETE)
112     {
113       log_error("ERROR: Test failed because the second wait event is complete and the first is not.(status: 0: %s and 1: %s)\n", IGetStatusString( status[ 0 ] ), IGetStatusString( status[ 1 ] ) );
114             clFinish( queue );
115             return -1;
116     }
117     }
118     else
119     {
120         if( status[ 0 ] == CL_COMPLETE )
121         {
122             log_info( "WARNING: Reference event completed, so unable to test further (implicitly passing).\n" );
123             clFinish( queue );
124             return 0;
125         }
126         if( status[ 0 ] != CL_RUNNING && status[ 0 ] != CL_QUEUED && status[ 0 ] != CL_SUBMITTED )
127         {
128             log_error( "ERROR: Test failed because first wait event is not currently running, queued, or submitted! (status: 0: %s)\n", IGetStatusString( status[ 0 ] ) );
129             clFinish( queue );
130             return -1;
131         }
132     }
133 
134     if( status[ 2 ] != CL_QUEUED && status[ 2 ] != CL_SUBMITTED )
135     {
136         log_error( "ERROR: Test event is not waiting to run! (status: 2: %s)\n", IGetStatusString( status[ 2 ] ) );
137         clFinish( queue );
138         return -1;
139     }
140 
141     // Now wait for the first reference event
142   if (PRINT_OPS) log_info("\tWaiting for action 1 to finish...\n");
143     error = clWaitForEvents( 1, &events[ 0 ] );
144     test_error( error, "Unable to wait for reference event" );
145 
146     // Grab statuses again
147   if (PRINT_OPS) log_info("\tChecking status of action to test 2...\n");
148     error = clGetEventInfo( events[ 2 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 2 ] ), &status[ 2 ], NULL );
149     test_error( error, "Unable to get event status" );
150   if( multiple ) {
151     if (PRINT_OPS) log_info("\tChecking status of action 1...\n");
152         error = clGetEventInfo( events[ 1 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 1 ] ), &status[ 1 ], NULL );
153     test_error( error, "Unable to get event status" );
154   }
155   if (PRINT_OPS) log_info("\tChecking status of action 0...\n");
156     error = clGetEventInfo( events[ 0 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 0 ] ), &status[ 0 ], NULL );
157   test_error( error, "Unable to get event status" );
158 
159   log_info("\t\tEvent status after waiting for reference event 0: reference event 0: %s, reference event 1: %s, test event 2: %s.\n",
160            IGetStatusString( status[ 0 ] ), (multiple ? IGetStatusString( status[ 1 ] ) : "N/A"), IGetStatusString( status[ 2 ] ));
161 
162     // Sanity
163     if( status[ 0 ] != CL_COMPLETE )
164     {
165         log_error( "ERROR: Waited for first event but it's not complete (status: 0: %s)\n", IGetStatusString( status[ 0 ] ) );
166         clFinish( queue );
167         return -1;
168     }
169 
170     // If we're multiple, and the second event isn't complete, then our test event should still be queued
171     if( multiple && status[ 1 ] != CL_COMPLETE )
172     {
173     if( status[ 1 ] == CL_RUNNING && status[ 2 ] == CL_RUNNING ) {
174       log_error("ERROR: Test event and second event are both running.\n");
175       clFinish( queue );
176       return -1;
177     }
178         if( status[ 2 ] != CL_QUEUED && status[ 2 ] != CL_SUBMITTED )
179         {
180             log_error( "ERROR: Test event did not wait for second event before starting! (status of ref: 1: %s, of test: 2: %s)\n", IGetStatusString( status[ 1 ] ), IGetStatusString( status[ 2 ] ) );
181             clFinish( queue );
182             return -1;
183         }
184 
185         // Now wait for second event to complete, too
186     if (PRINT_OPS) log_info("\tWaiting for action 1 to finish...\n");
187         error = clWaitForEvents( 1, &events[ 1 ] );
188         test_error( error, "Unable to wait for second reference event" );
189 
190         // Grab statuses again
191     if (PRINT_OPS) log_info("\tChecking status of action to test 2...\n");
192     error = clGetEventInfo( events[ 2 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 2 ] ), &status[ 2 ], NULL );
193     test_error( error, "Unable to get event status" );
194     if( multiple ) {
195       if (PRINT_OPS) log_info("\tChecking status of action 1...\n");
196       error = clGetEventInfo( events[ 1 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 1 ] ), &status[ 1 ], NULL );
197       test_error( error, "Unable to get event status" );
198     }
199     if (PRINT_OPS) log_info("\tChecking status of action 0...\n");
200     error = clGetEventInfo( events[ 0 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 0 ] ), &status[ 0 ], NULL );
201     test_error( error, "Unable to get event status" );
202 
203     log_info("\t\tEvent status after waiting for reference event 1: reference event 0: %s, reference event 1: %s, test event 2: %s.\n",
204              IGetStatusString( status[ 0 ] ), (multiple ? IGetStatusString( status[ 1 ] ) : "N/A"), IGetStatusString( status[ 2 ] ));
205 
206         // Sanity
207         if( status[ 1 ] != CL_COMPLETE )
208         {
209             log_error( "ERROR: Waited for second reference event but it didn't complete (status: 1: %s)\n", IGetStatusString( status[ 1 ] ) );
210             clFinish( queue );
211             return -1;
212         }
213     }
214 
215     // At this point, the test event SHOULD be running, but if it completed, we consider it a pass
216     if( status[ 2 ] == CL_COMPLETE )
217     {
218         log_info( "WARNING: Test event already completed. Assumed valid.\n" );
219         clFinish( queue );
220         return 0;
221     }
222     if( status[ 2 ] != CL_RUNNING && status[ 2 ] != CL_SUBMITTED && status[ 2 ] != CL_QUEUED)
223     {
224         log_error( "ERROR: Second event did not start running after reference event(s) completed! (status: 2: %s)\n", IGetStatusString( status[ 2 ] ) );
225         clFinish( queue );
226         return -1;
227     }
228 
229     // Wait for the test event, then return
230   if (PRINT_OPS) log_info("\tWaiting for action 2 to test to finish...\n");
231     error = clWaitForEvents( 1, &events[ 2 ] );
232     test_error( error, "Unable to wait for test event" );
233 
234   error |= clGetEventInfo( events[ 2 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 2 ] ), &status[ 2 ], NULL );
235   test_error( error, "Unable to get event status" );
236 
237   log_info("\t\tEvent status after waiting for test event: reference event 0: %s, reference event 1: %s, test event 2: %s.\n",
238            IGetStatusString( status[ 0 ] ), (multiple ? IGetStatusString( status[ 1 ] ) : "N/A"), IGetStatusString( status[ 2 ] ));
239 
240   // Sanity
241   if( status[ 2 ] != CL_COMPLETE )
242   {
243     log_error( "ERROR: Test event didn't complete (status: 2: %s)\n", IGetStatusString( status[ 2 ] ) );
244     clFinish( queue );
245     return -1;
246   }
247 
248   clFinish(queue);
249     return 0;
250 }
251 
252 #define TEST_ACTION( name ) \
253     {    \
254         name##Action action;    \
255         log_info( "-- Testing " #name " (waiting on 1 event)...\n" );    \
256         if( ( error = test_waitlist( deviceID, context, queue, &action, false ) ) != CL_SUCCESS )    \
257             retVal++;            \
258         clFinish( queue ); \
259     }    \
260     if( error == CL_SUCCESS )    /* Only run multiples test if single test passed */ \
261     {    \
262         name##Action action;    \
263         log_info( "-- Testing " #name " (waiting on 2 events)...\n" );    \
264         if( ( error = test_waitlist( deviceID, context, queue, &action, true ) ) != CL_SUCCESS )    \
265             retVal++;            \
266         clFinish( queue ); \
267     }
268 
test_waitlists(cl_device_id deviceID,cl_context context,cl_command_queue oldQueue,int num_elements)269 int test_waitlists( cl_device_id deviceID, cl_context context, cl_command_queue oldQueue, int num_elements )
270 {
271     cl_int error;
272     int retVal = 0;
273     cl_command_queue_properties props = CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE;
274 
275     if( !checkDeviceForQueueSupport( deviceID, props ) )
276     {
277         log_info( "WARNING: Device does not support out-of-order exec mode; skipping test.\n" );
278         return 0;
279     }
280 
281     clCommandQueueWrapper queue = clCreateCommandQueue( context, deviceID, props, &error );
282     test_error(error, "Unable to create out-of-order queue");
283 
284     log_info( "\n" );
285 
286     TEST_ACTION( NDRangeKernel )
287 
288     TEST_ACTION( ReadBuffer )
289     TEST_ACTION( WriteBuffer )
290     TEST_ACTION( MapBuffer )
291     TEST_ACTION( UnmapBuffer )
292 
293     if( checkForImageSupport( deviceID ) == CL_IMAGE_FORMAT_NOT_SUPPORTED )
294     {
295         log_info( "\nNote: device does not support images. Skipping remainder of waitlist tests...\n" );
296     }
297     else
298     {
299         TEST_ACTION( ReadImage2D )
300         TEST_ACTION( WriteImage2D )
301         TEST_ACTION( CopyImage2Dto2D )
302         TEST_ACTION( Copy2DImageToBuffer )
303         TEST_ACTION( CopyBufferTo2DImage )
304         TEST_ACTION( MapImage )
305 
306         if( checkFor3DImageSupport( deviceID ) == CL_IMAGE_FORMAT_NOT_SUPPORTED )
307             log_info("Device does not support 3D images. Skipping remainder of waitlist tests...\n");
308         else
309         {
310             TEST_ACTION( ReadImage3D )
311             TEST_ACTION( WriteImage3D )
312             TEST_ACTION( CopyImage2Dto3D )
313             TEST_ACTION( CopyImage3Dto2D )
314             TEST_ACTION( CopyImage3Dto3D )
315             TEST_ACTION( Copy3DImageToBuffer )
316             TEST_ACTION( CopyBufferTo3DImage )
317         }
318     }
319 
320     return retVal;
321 }
322 
323