Skip to content

Commit d427afc

Browse files
committed
[cl] Permit size 0 in clEnqueue(Read|Write|Copy|Fill)Buffer
This is not explicitly forbidden by the current unified OpenCL specification for clEnqueueReadBuffer, clEnqueueWriteBuffer, or clEnqueueCopyBuffer; though it *was* forbidden up until OpenCL 2.0. Therefore, make the checks for size 0 dependent on the OpenCL version being built. A size of zero for clEnqueueFillBuffer has always been valid, so explicitly test that. The `muxCommandFillBuffer` function forbids a size of 0, so it was a bug to call that function when size was 0.
1 parent 7cd729b commit d427afc

File tree

6 files changed

+94
-54
lines changed

6 files changed

+94
-54
lines changed

source/cl/source/buffer.cpp

Lines changed: 55 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,9 @@ cl::EnqueueWriteBuffer(cl_command_queue command_queue, cl_mem buffer,
841841
return CL_INVALID_CONTEXT);
842842
OCL_CHECK(buffer->size < (offset + size), return CL_INVALID_VALUE);
843843
OCL_CHECK(!ptr, return CL_INVALID_VALUE);
844+
#if CL_TARGET_OPENCL_VERSION < 210
844845
OCL_CHECK(0 == size, return CL_INVALID_VALUE);
846+
#endif
845847
OCL_CHECK(cl::validate::IsInBitSet(buffer->flags, CL_MEM_HOST_READ_ONLY),
846848
return CL_INVALID_OPERATION);
847849
OCL_CHECK(cl::validate::IsInBitSet(buffer->flags, CL_MEM_HOST_NO_ACCESS),
@@ -873,18 +875,20 @@ cl::EnqueueWriteBuffer(cl_command_queue command_queue, cl_mem buffer,
873875
return CL_OUT_OF_RESOURCES;
874876
}
875877

876-
auto device_index = command_queue->getDeviceIndex();
877-
auto mux_buffer =
878-
static_cast<cl_mem_buffer>(buffer)->mux_buffers[device_index];
879-
auto mux_error =
880-
muxCommandWriteBuffer(*mux_command_buffer, mux_buffer, offset, ptr,
881-
size, 0, nullptr, nullptr);
882-
if (mux_error) {
883-
auto error = cl::getErrorFrom(mux_error);
884-
if (event_release_guard) {
885-
event_release_guard->complete(error);
878+
if (0 != size) {
879+
auto device_index = command_queue->getDeviceIndex();
880+
auto mux_buffer =
881+
static_cast<cl_mem_buffer>(buffer)->mux_buffers[device_index];
882+
auto mux_error =
883+
muxCommandWriteBuffer(*mux_command_buffer, mux_buffer, offset, ptr,
884+
size, 0, nullptr, nullptr);
885+
if (mux_error) {
886+
auto error = cl::getErrorFrom(mux_error);
887+
if (event_release_guard) {
888+
event_release_guard->complete(error);
889+
}
890+
return error;
886891
}
887-
return error;
888892
}
889893

890894
cl::retainInternal(buffer);
@@ -928,7 +932,9 @@ CL_API_ENTRY cl_int CL_API_CALL cl::EnqueueReadBuffer(
928932
return CL_INVALID_CONTEXT);
929933
OCL_CHECK(buffer->size < (offset + size), return CL_INVALID_VALUE);
930934
OCL_CHECK(!ptr, return CL_INVALID_VALUE);
935+
#if CL_TARGET_OPENCL_VERSION < 210
931936
OCL_CHECK(0 == size, return CL_INVALID_VALUE);
937+
#endif
932938
OCL_CHECK(cl::validate::IsInBitSet(buffer->flags, CL_MEM_HOST_WRITE_ONLY),
933939
return CL_INVALID_OPERATION);
934940
OCL_CHECK(cl::validate::IsInBitSet(buffer->flags, CL_MEM_HOST_NO_ACCESS),
@@ -960,14 +966,16 @@ CL_API_ENTRY cl_int CL_API_CALL cl::EnqueueReadBuffer(
960966
return CL_OUT_OF_RESOURCES;
961967
}
962968

963-
auto device_index = command_queue->getDeviceIndex();
964-
auto mux_buffer =
965-
static_cast<cl_mem_buffer>(buffer)->mux_buffers[device_index];
966-
auto mux_error =
967-
muxCommandReadBuffer(*mux_command_buffer, mux_buffer, offset, ptr, size,
968-
0, nullptr, nullptr);
969-
if (mux_error) {
970-
return cl::getErrorFrom(mux_error);
969+
if (0 != size) {
970+
auto device_index = command_queue->getDeviceIndex();
971+
auto mux_buffer =
972+
static_cast<cl_mem_buffer>(buffer)->mux_buffers[device_index];
973+
auto mux_error =
974+
muxCommandReadBuffer(*mux_command_buffer, mux_buffer, offset, ptr,
975+
size, 0, nullptr, nullptr);
976+
if (mux_error) {
977+
return cl::getErrorFrom(mux_error);
978+
}
971979
}
972980

973981
cl::retainInternal(buffer);
@@ -1038,20 +1046,22 @@ cl::EnqueueCopyBuffer(cl_command_queue command_queue, cl_mem src_buffer,
10381046
return CL_OUT_OF_RESOURCES;
10391047
}
10401048

1041-
auto device_index = command_queue->getDeviceIndex();
1042-
auto mux_src_buffer =
1043-
static_cast<cl_mem_buffer>(src_buffer)->mux_buffers[device_index];
1044-
auto mux_dst_buffer =
1045-
static_cast<cl_mem_buffer>(dst_buffer)->mux_buffers[device_index];
1046-
auto mux_error = muxCommandCopyBuffer(*mux_command_buffer, mux_src_buffer,
1047-
src_offset, mux_dst_buffer, dst_offset,
1048-
size, 0, nullptr, nullptr);
1049-
if (mux_error) {
1050-
auto error = cl::getErrorFrom(mux_error);
1051-
if (return_event) {
1052-
return_event->complete(error);
1049+
if (0 != size) {
1050+
auto device_index = command_queue->getDeviceIndex();
1051+
auto mux_src_buffer =
1052+
static_cast<cl_mem_buffer>(src_buffer)->mux_buffers[device_index];
1053+
auto mux_dst_buffer =
1054+
static_cast<cl_mem_buffer>(dst_buffer)->mux_buffers[device_index];
1055+
auto mux_error = muxCommandCopyBuffer(
1056+
*mux_command_buffer, mux_src_buffer, src_offset, mux_dst_buffer,
1057+
dst_offset, size, 0, nullptr, nullptr);
1058+
if (mux_error) {
1059+
auto error = cl::getErrorFrom(mux_error);
1060+
if (return_event) {
1061+
return_event->complete(error);
1062+
}
1063+
return error;
10531064
}
1054-
return error;
10551065
}
10561066

10571067
cl::retainInternal(src_buffer);
@@ -1104,18 +1114,20 @@ cl::EnqueueFillBuffer(cl_command_queue command_queue, cl_mem buffer,
11041114
return CL_OUT_OF_RESOURCES;
11051115
}
11061116

1107-
auto device_index = command_queue->getDeviceIndex();
1108-
auto mux_buffer =
1109-
static_cast<cl_mem_buffer>(buffer)->mux_buffers[device_index];
1110-
auto mux_error =
1111-
muxCommandFillBuffer(*mux_command_buffer, mux_buffer, offset, size,
1112-
pattern, pattern_size, 0, nullptr, nullptr);
1113-
if (mux_error) {
1114-
auto error = cl::getErrorFrom(mux_error);
1115-
if (return_event) {
1116-
return_event->complete(error);
1117+
if (0 != size) {
1118+
auto device_index = command_queue->getDeviceIndex();
1119+
auto mux_buffer =
1120+
static_cast<cl_mem_buffer>(buffer)->mux_buffers[device_index];
1121+
auto mux_error =
1122+
muxCommandFillBuffer(*mux_command_buffer, mux_buffer, offset, size,
1123+
pattern, pattern_size, 0, nullptr, nullptr);
1124+
if (mux_error) {
1125+
auto error = cl::getErrorFrom(mux_error);
1126+
if (return_event) {
1127+
return_event->complete(error);
1128+
}
1129+
return error;
11171130
}
1118-
return error;
11191131
}
11201132

11211133
cl::retainInternal(buffer);

source/cl/source/validate.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,9 @@ cl_int CopyBufferArguments(cl_command_queue command_queue, cl_mem src_buffer,
124124
return CL_INVALID_VALUE);
125125
OCL_CHECK(src_offset + size > src_buffer->size, return CL_INVALID_VALUE);
126126
OCL_CHECK(dst_offset + size > dst_buffer->size, return CL_INVALID_VALUE);
127+
#if CL_TARGET_OPENCL_VERSION < 210
127128
OCL_CHECK(size == 0, return CL_INVALID_VALUE);
129+
#endif
128130
size_t src_start = src_offset;
129131
size_t dst_start = dst_offset;
130132
size_t src_buffer_size = 0;

source/cl/test/UnitCL/source/clEnqueueCopyBuffer.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "Common.h"
1818
#include "EventWaitList.h"
19+
#include "ucl/checks.h"
1920

2021
class clEnqueueCopyBufferCheckTest : public ucl::CommandQueueTest {
2122
protected:
@@ -296,9 +297,15 @@ TEST_F(clEnqueueCopyBufferCheckTest, dst_bufferSizePlusOffsetTooLarge) {
296297
}
297298

298299
TEST_F(clEnqueueCopyBufferCheckTest, BufferSizeZero) {
299-
ASSERT_EQ_ERRCODE(CL_INVALID_VALUE,
300-
clEnqueueCopyBuffer(command_queue, src_buffer, src_buffer,
301-
0, 0, 0, 0, nullptr, nullptr));
300+
// An error when size == 0 was removed starting with OpenCL 2.1.
301+
if (UCL::isDeviceVersionAtLeast({2, 1})) {
302+
ASSERT_SUCCESS(clEnqueueCopyBuffer(command_queue, src_buffer, src_buffer, 0,
303+
0, 0, 0, nullptr, nullptr));
304+
} else {
305+
ASSERT_EQ_ERRCODE(CL_INVALID_VALUE,
306+
clEnqueueCopyBuffer(command_queue, src_buffer, src_buffer,
307+
0, 0, 0, 0, nullptr, nullptr));
308+
}
302309
}
303310

304311
TEST_F(clEnqueueCopyBufferTest, CopyBufferNoEvents) {

source/cl/test/UnitCL/source/clEnqueueFillBuffer.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
//
1515
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
1616

17+
#include <CL/cl.h>
18+
1719
#include <array>
1820

1921
#include "Common.h"
@@ -122,6 +124,11 @@ TEST_F(clEnqueueFillBufferTest, ZeroPatternSize) {
122124
size, 0, nullptr, nullptr));
123125
}
124126

127+
TEST_F(clEnqueueFillBufferTest, SizeZero) {
128+
ASSERT_SUCCESS(clEnqueueFillBuffer(command_queue, buffer, &pattern,
129+
pattern_size, 0, 0, 0, nullptr, nullptr));
130+
}
131+
125132
TEST_F(clEnqueueFillBufferTest, BadPatternSizes) {
126133
EXPECT_EQ_ERRCODE(CL_INVALID_VALUE,
127134
clEnqueueFillBuffer(command_queue, buffer, &pattern, 3, 0,

source/cl/test/UnitCL/source/clEnqueueReadBuffer.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,16 @@ TEST_F(clEnqueueReadBufferTest, InvalidBuffer) {
210210
0, nullptr, nullptr));
211211
}
212212

213-
TEST_F(clEnqueueReadBufferTest, InvalidSize) {
214-
ASSERT_EQ_ERRCODE(CL_INVALID_VALUE,
215-
clEnqueueReadBuffer(command_queue, inMem, CL_TRUE, 0, 0,
216-
inBuffer, 0, nullptr, nullptr));
213+
TEST_F(clEnqueueReadBufferTest, SizeZero) {
214+
// An error when size == 0 was removed starting with OpenCL 2.1.
215+
if (UCL::isDeviceVersionAtLeast({2, 1})) {
216+
ASSERT_SUCCESS(clEnqueueReadBuffer(command_queue, inMem, CL_TRUE, 0, 0,
217+
inBuffer, 0, nullptr, nullptr));
218+
} else {
219+
ASSERT_EQ_ERRCODE(CL_INVALID_VALUE,
220+
clEnqueueReadBuffer(command_queue, inMem, CL_TRUE, 0, 0,
221+
inBuffer, 0, nullptr, nullptr));
222+
}
217223
}
218224

219225
TEST_F(clEnqueueReadBufferTest, NullWaitList) {

source/cl/test/UnitCL/source/clEnqueueWriteBuffer.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,16 @@ TEST_F(clEnqueueWriteBufferTest, InvalidBuffer) {
104104
nullptr, 0, nullptr, nullptr));
105105
}
106106

107-
TEST_F(clEnqueueWriteBufferTest, InvalidSize) {
108-
ASSERT_EQ_ERRCODE(CL_INVALID_VALUE,
109-
clEnqueueWriteBuffer(command_queue, mem, true, 0, 0,
110-
&buffer[0], 0, nullptr, nullptr));
107+
TEST_F(clEnqueueWriteBufferTest, SizeZero) {
108+
// An error when size == 0 was removed starting with OpenCL 2.1.
109+
if (UCL::isDeviceVersionAtLeast({2, 1})) {
110+
ASSERT_SUCCESS(clEnqueueWriteBuffer(command_queue, mem, true, 0, 0,
111+
&buffer[0], 0, nullptr, nullptr));
112+
} else {
113+
ASSERT_EQ_ERRCODE(CL_INVALID_VALUE,
114+
clEnqueueWriteBuffer(command_queue, mem, true, 0, 0,
115+
&buffer[0], 0, nullptr, nullptr));
116+
}
111117
}
112118

113119
TEST_F(clEnqueueWriteBufferTest, WriteToReadOnly) {

0 commit comments

Comments
 (0)