Files
OpenCL-CTS/test_conformance/events/test_waitlists.cpp
Ahmed Hesham c4fa48db05 Migrate events suite to the new test registration framework (#2324)
Contributes to #2181.

Signed-off-by: Ahmed Hesham <ahmed.hesham@arm.com>
2025-03-11 21:57:59 +00:00

393 lines
15 KiB
C++

//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "testBase.h"
#include "action_classes.h"
extern const char *IGetStatusString(cl_int status);
#define PRINT_OPS 0
static int test_waitlist(cl_device_id device, cl_context context,
cl_command_queue queue, Action *actionToTest,
bool multiple)
{
NDRangeKernelAction actions[2];
clEventWrapper events[3];
cl_int status[3];
cl_int error;
if (multiple)
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");
else
log_info("\tExecuting reference event 0, then test event 2 with "
"reference event 0 in its waitlist.\n");
// Set up the first base action to wait against
error = actions[0].Setup(device, context, queue);
test_error(error, "Unable to setup base event to wait against");
if (multiple)
{
// Set up a second event to wait against
error = actions[1].Setup(device, context, queue);
test_error(error, "Unable to setup second base event to wait against");
}
// Now set up the actual action to test
error = actionToTest->Setup(device, context, queue);
test_error(error, "Unable to set up test event");
// Execute all events now
if (PRINT_OPS) log_info("\tExecuting action 0...\n");
error = actions[0].Execute(queue, 0, NULL, &events[0]);
test_error(error, "Unable to execute first event");
if (multiple)
{
if (PRINT_OPS) log_info("\tExecuting action 1...\n");
error = actions[1].Execute(queue, 1, &events[0], &events[1]);
test_error(error, "Unable to execute second event");
}
// Sanity check
if (multiple)
{
if (PRINT_OPS) log_info("\tChecking status of action 1...\n");
error = clGetEventInfo(events[1], CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(status[1]), &status[1], NULL);
test_error(error, "Unable to get event status");
}
if (PRINT_OPS) log_info("\tChecking status of action 0...\n");
error = clGetEventInfo(events[0], CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(status[0]), &status[0], NULL);
test_error(error, "Unable to get event status");
log_info("\t\tEvent status after starting reference events: reference "
"event 0: %s, reference event 1: %s, test event 2: %s.\n",
IGetStatusString(status[0]),
(multiple ? IGetStatusString(status[1]) : "N/A"), "N/A");
if ((status[0] == CL_COMPLETE) || (multiple && status[1] == CL_COMPLETE))
{
log_info("WARNING: Reference event(s) already completed before we "
"could execute test event! Possible that the reference event "
"blocked (implicitly passing)\n");
return 0;
}
if (PRINT_OPS) log_info("\tExecuting action to test...\n");
error = actionToTest->Execute(queue, (multiple) ? 2 : 1, &events[0],
&events[2]);
test_error(error, "Unable to execute test event");
// Hopefully, the first event is still running
if (PRINT_OPS) log_info("\tChecking status of action to test 2...\n");
error = clGetEventInfo(events[2], CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(status[2]), &status[2], NULL);
test_error(error, "Unable to get event status");
if (multiple)
{
if (PRINT_OPS) log_info("\tChecking status of action 1...\n");
error = clGetEventInfo(events[1], CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(status[1]), &status[1], NULL);
test_error(error, "Unable to get event status");
}
if (PRINT_OPS) log_info("\tChecking status of action 0...\n");
error = clGetEventInfo(events[0], CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(status[0]), &status[0], NULL);
test_error(error, "Unable to get event status");
log_info("\t\tEvent status after starting test event: reference event 0: "
"%s, reference event 1: %s, test event 2: %s.\n",
IGetStatusString(status[0]),
(multiple ? IGetStatusString(status[1]) : "N/A"),
IGetStatusString(status[2]));
if (multiple)
{
if (status[0] == CL_COMPLETE && status[1] == CL_COMPLETE)
{
log_info("WARNING: Both events completed, so unable to test "
"further (implicitly passing).\n");
clFinish(queue);
return 0;
}
if (status[1] == CL_COMPLETE && status[0] != CL_COMPLETE)
{
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]));
clFinish(queue);
return -1;
}
}
else
{
if (status[0] == CL_COMPLETE)
{
log_info("WARNING: Reference event completed, so unable to test "
"further (implicitly passing).\n");
clFinish(queue);
return 0;
}
if (status[0] != CL_RUNNING && status[0] != CL_QUEUED
&& status[0] != CL_SUBMITTED)
{
log_error(
"ERROR: Test failed because first wait event is not currently "
"running, queued, or submitted! (status: 0: %s)\n",
IGetStatusString(status[0]));
clFinish(queue);
return -1;
}
}
if (status[2] != CL_QUEUED && status[2] != CL_SUBMITTED)
{
log_error("ERROR: Test event is not waiting to run! (status: 2: %s)\n",
IGetStatusString(status[2]));
clFinish(queue);
return -1;
}
// Now wait for the first reference event
if (PRINT_OPS) log_info("\tWaiting for action 1 to finish...\n");
error = clWaitForEvents(1, &events[0]);
test_error(error, "Unable to wait for reference event");
// Grab statuses again
if (PRINT_OPS) log_info("\tChecking status of action to test 2...\n");
error = clGetEventInfo(events[2], CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(status[2]), &status[2], NULL);
test_error(error, "Unable to get event status");
if (multiple)
{
if (PRINT_OPS) log_info("\tChecking status of action 1...\n");
error = clGetEventInfo(events[1], CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(status[1]), &status[1], NULL);
test_error(error, "Unable to get event status");
}
if (PRINT_OPS) log_info("\tChecking status of action 0...\n");
error = clGetEventInfo(events[0], CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(status[0]), &status[0], NULL);
test_error(error, "Unable to get event status");
log_info("\t\tEvent status after waiting for reference event 0: reference "
"event 0: %s, reference event 1: %s, test event 2: %s.\n",
IGetStatusString(status[0]),
(multiple ? IGetStatusString(status[1]) : "N/A"),
IGetStatusString(status[2]));
// Sanity
if (status[0] != CL_COMPLETE)
{
log_error("ERROR: Waited for first event but it's not complete "
"(status: 0: %s)\n",
IGetStatusString(status[0]));
clFinish(queue);
return -1;
}
// If we're multiple, and the second event isn't complete, then our test
// event should still be queued
if (multiple && status[1] != CL_COMPLETE)
{
if (status[1] == CL_RUNNING && status[2] == CL_RUNNING)
{
log_error("ERROR: Test event and second event are both running.\n");
clFinish(queue);
return -1;
}
if (status[2] != CL_QUEUED && status[2] != CL_SUBMITTED)
{
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]));
clFinish(queue);
return -1;
}
// Now wait for second event to complete, too
if (PRINT_OPS) log_info("\tWaiting for action 1 to finish...\n");
error = clWaitForEvents(1, &events[1]);
test_error(error, "Unable to wait for second reference event");
// Grab statuses again
if (PRINT_OPS) log_info("\tChecking status of action to test 2...\n");
error = clGetEventInfo(events[2], CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(status[2]), &status[2], NULL);
test_error(error, "Unable to get event status");
if (multiple)
{
if (PRINT_OPS) log_info("\tChecking status of action 1...\n");
error = clGetEventInfo(events[1], CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(status[1]), &status[1], NULL);
test_error(error, "Unable to get event status");
}
if (PRINT_OPS) log_info("\tChecking status of action 0...\n");
error = clGetEventInfo(events[0], CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(status[0]), &status[0], NULL);
test_error(error, "Unable to get event status");
log_info(
"\t\tEvent status after waiting for reference event 1: reference "
"event 0: %s, reference event 1: %s, test event 2: %s.\n",
IGetStatusString(status[0]),
(multiple ? IGetStatusString(status[1]) : "N/A"),
IGetStatusString(status[2]));
// Sanity
if (status[1] != CL_COMPLETE)
{
log_error("ERROR: Waited for second reference event but it didn't "
"complete (status: 1: %s)\n",
IGetStatusString(status[1]));
clFinish(queue);
return -1;
}
}
// At this point, the test event SHOULD be running, but if it completed, we
// consider it a pass
if (status[2] == CL_COMPLETE)
{
log_info("WARNING: Test event already completed. Assumed valid.\n");
clFinish(queue);
return 0;
}
if (status[2] != CL_RUNNING && status[2] != CL_SUBMITTED
&& status[2] != CL_QUEUED)
{
log_error("ERROR: Second event did not start running after reference "
"event(s) completed! (status: 2: %s)\n",
IGetStatusString(status[2]));
clFinish(queue);
return -1;
}
// Wait for the test event, then return
if (PRINT_OPS) log_info("\tWaiting for action 2 to test to finish...\n");
error = clWaitForEvents(1, &events[2]);
test_error(error, "Unable to wait for test event");
error |= clGetEventInfo(events[2], CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(status[2]), &status[2], NULL);
test_error(error, "Unable to get event status");
log_info("\t\tEvent status after waiting for test event: reference event "
"0: %s, reference event 1: %s, test event 2: %s.\n",
IGetStatusString(status[0]),
(multiple ? IGetStatusString(status[1]) : "N/A"),
IGetStatusString(status[2]));
// Sanity
if (status[2] != CL_COMPLETE)
{
log_error("ERROR: Test event didn't complete (status: 2: %s)\n",
IGetStatusString(status[2]));
clFinish(queue);
return -1;
}
clFinish(queue);
return 0;
}
#define TEST_ACTION(name) \
{ \
name##Action action; \
log_info("-- Testing " #name " (waiting on 1 event)...\n"); \
if ((error = \
test_waitlist(device, context, test_queue, &action, false)) \
!= CL_SUCCESS) \
retVal++; \
clFinish(test_queue); \
} \
if (error \
== CL_SUCCESS) /* Only run multiples test if single test passed */ \
{ \
name##Action action; \
log_info("-- Testing " #name " (waiting on 2 events)...\n"); \
if ((error = \
test_waitlist(device, context, test_queue, &action, true)) \
!= CL_SUCCESS) \
retVal++; \
clFinish(test_queue); \
}
REGISTER_TEST(waitlists)
{
cl_int error;
int retVal = 0;
cl_command_queue_properties props = CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE;
if (!checkDeviceForQueueSupport(device, props))
{
log_info("WARNING: Device does not support out-of-order exec mode; "
"skipping test.\n");
return 0;
}
clCommandQueueWrapper test_queue =
clCreateCommandQueue(context, device, props, &error);
test_error(error, "Unable to create out-of-order queue");
log_info("\n");
TEST_ACTION(NDRangeKernel)
TEST_ACTION(ReadBuffer)
TEST_ACTION(WriteBuffer)
TEST_ACTION(MapBuffer)
TEST_ACTION(UnmapBuffer)
if (checkForImageSupport(device) == CL_IMAGE_FORMAT_NOT_SUPPORTED)
{
log_info("\nNote: device does not support images. Skipping remainder "
"of waitlist tests...\n");
}
else
{
TEST_ACTION(ReadImage2D)
TEST_ACTION(WriteImage2D)
TEST_ACTION(CopyImage2Dto2D)
TEST_ACTION(Copy2DImageToBuffer)
TEST_ACTION(CopyBufferTo2DImage)
TEST_ACTION(MapImage)
if (checkFor3DImageSupport(device) == CL_IMAGE_FORMAT_NOT_SUPPORTED)
log_info("Device does not support 3D images. Skipping remainder of "
"waitlist tests...\n");
else
{
TEST_ACTION(ReadImage3D)
TEST_ACTION(WriteImage3D)
TEST_ACTION(CopyImage2Dto3D)
TEST_ACTION(CopyImage3Dto2D)
TEST_ACTION(CopyImage3Dto3D)
TEST_ACTION(Copy3DImageToBuffer)
TEST_ACTION(CopyBufferTo3DImage)
}
}
return retVal;
}