diff --git a/test_conformance/extensions/cl_khr_command_buffer/basic_command_buffer.cpp b/test_conformance/extensions/cl_khr_command_buffer/basic_command_buffer.cpp index 43926b84..9c3a402b 100644 --- a/test_conformance/extensions/cl_khr_command_buffer/basic_command_buffer.cpp +++ b/test_conformance/extensions/cl_khr_command_buffer/basic_command_buffer.cpp @@ -435,3 +435,40 @@ bool InterleavedEnqueueTest::Skip() { return BasicCommandBufferTest::Skip() || !simultaneous_use_support; } + +cl_int EnqueueAndReleaseTest::Run() +{ + cl_int error = clCommandNDRangeKernelKHR( + command_buffer, nullptr, nullptr, kernel, 1, nullptr, &num_elements, + nullptr, 0, nullptr, nullptr, nullptr); + test_error(error, "clCommandNDRangeKernelKHR failed"); + + error = clFinalizeCommandBufferKHR(command_buffer); + test_error(error, "clFinalizeCommandBufferKHR failed"); + + cl_int pattern = 42; + error = clEnqueueFillBuffer(queue, in_mem, &pattern, sizeof(cl_int), 0, + data_size(), 0, nullptr, nullptr); + test_error(error, "clEnqueueFillBuffer failed"); + + error = clEnqueueCommandBufferKHR(0, nullptr, command_buffer, 0, nullptr, + nullptr); + test_error(error, "clEnqueueCommandBufferKHR failed"); + + // Calls release on cl_command_buffer_khr handle inside wrapper class, and + // sets the handle to nullptr, so that release doesn't get called again at + // end of test when wrapper object is destroyed. + command_buffer.reset(); + + std::vector output_data(num_elements); + error = clEnqueueReadBuffer(queue, out_mem, CL_TRUE, 0, data_size(), + output_data.data(), 0, nullptr, nullptr); + test_error(error, "clEnqueueReadBuffer failed"); + + for (size_t i = 0; i < num_elements; i++) + { + CHECK_VERIFICATION_ERROR(pattern, output_data[i], i); + } + + return CL_SUCCESS; +} diff --git a/test_conformance/extensions/cl_khr_command_buffer/basic_command_buffer.h b/test_conformance/extensions/cl_khr_command_buffer/basic_command_buffer.h index 7ad7d28d..241a08c5 100644 --- a/test_conformance/extensions/cl_khr_command_buffer/basic_command_buffer.h +++ b/test_conformance/extensions/cl_khr_command_buffer/basic_command_buffer.h @@ -128,6 +128,15 @@ struct InterleavedEnqueueTest : public BasicCommandBufferTest bool Skip() override; }; +// Test releasing a command-buffer after it has been submitted for execution, +// but before the user has waited on completion of the enqueue. +struct EnqueueAndReleaseTest : public BasicCommandBufferTest +{ + using BasicCommandBufferTest::BasicCommandBufferTest; + + cl_int Run() override; +}; + template int MakeAndRunTest(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements) diff --git a/test_conformance/extensions/cl_khr_command_buffer/basic_command_buffer_tests.cpp b/test_conformance/extensions/cl_khr_command_buffer/basic_command_buffer_tests.cpp index 0f95372a..69d554c4 100644 --- a/test_conformance/extensions/cl_khr_command_buffer/basic_command_buffer_tests.cpp +++ b/test_conformance/extensions/cl_khr_command_buffer/basic_command_buffer_tests.cpp @@ -44,3 +44,9 @@ REGISTER_TEST(explicit_flush) return MakeAndRunTest(device, context, queue, num_elements); } + +REGISTER_TEST(enqueue_and_release) +{ + return MakeAndRunTest(device, context, queue, + num_elements); +}