Test releasing a command-buffer after submission but before execution has finished (#2414)

Add cl_khr_command_buffer test that is it valid to release a
command-buffer after it has been enqueued but before execution is
finished.

This stresses the semantics from
[clReleaseCommandBufferKHR](https://registry.khronos.org/OpenCL/sdk/3.0/docs/man/html/clReleaseCommandBufferKHR.html#_description)
that: "After the command_buffer reference count becomes zero **and has
finished execution**, the command-buffer is deleted"
This commit is contained in:
Ewan Crawford
2025-07-08 00:35:20 +01:00
committed by GitHub
parent 3065a62f77
commit 5997a00b2f
3 changed files with 52 additions and 0 deletions

View File

@@ -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<cl_int> 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;
}

View File

@@ -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 <class T>
int MakeAndRunTest(cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements)

View File

@@ -44,3 +44,9 @@ REGISTER_TEST(explicit_flush)
return MakeAndRunTest<ExplicitFlushTest>(device, context, queue,
num_elements);
}
REGISTER_TEST(enqueue_and_release)
{
return MakeAndRunTest<EnqueueAndReleaseTest>(device, context, queue,
num_elements);
}