add tests for clCommandSVMMemcpyKHR & clCommandSVMMemfillKHR (#1821)

* add tests for clCommandSVMMemcpyKHR & clCommandSVMMemfillKHR

* Fix typo SVMMemfill -> SVMMemFill

* fix clCommandSVMMemFillKHR calls to match extension

* add Khronos license + minor fixes

* review fixes
This commit is contained in:
Michal Babej
2023-10-10 19:22:50 +03:00
committed by GitHub
parent a7c33f8dc4
commit af2710355d
10 changed files with 342 additions and 11 deletions

View File

@@ -145,6 +145,48 @@ using clSamplerWrapper =
using clEventWrapper =
wrapper_details::Wrapper<cl_event, clRetainEvent, clReleaseEvent>;
class clSVMWrapper {
void *Ptr = nullptr;
cl_context Ctx = nullptr;
public:
clSVMWrapper() = default;
clSVMWrapper(cl_context C, size_t Size,
cl_svm_mem_flags F = CL_MEM_READ_WRITE)
: Ctx(C)
{
Ptr = clSVMAlloc(C, F, Size, 0);
}
clSVMWrapper &operator=(void *other) = delete;
clSVMWrapper(clSVMWrapper const &other) = delete;
clSVMWrapper &operator=(clSVMWrapper const &other) = delete;
clSVMWrapper(clSVMWrapper &&other)
{
Ptr = other.Ptr;
Ctx = other.Ctx;
other.Ptr = nullptr;
other.Ctx = nullptr;
}
clSVMWrapper &operator=(clSVMWrapper &&other)
{
Ptr = other.Ptr;
Ctx = other.Ctx;
other.Ptr = nullptr;
other.Ctx = nullptr;
return *this;
}
~clSVMWrapper()
{
if (Ptr) clSVMFree(Ctx, Ptr);
}
void *operator()() const { return Ptr; }
};
class clProtectedImage {
public:
clProtectedImage()

View File

@@ -3,6 +3,7 @@ set(MODULE_NAME CL_KHR_COMMAND_BUFFER)
set(${MODULE_NAME}_SOURCES
main.cpp
basic_command_buffer.cpp
svm_command_basic.cpp
command_buffer_printf.cpp
command_buffer_get_command_buffer_info.cpp
command_buffer_set_kernel_arg.cpp

View File

@@ -34,6 +34,18 @@
} \
}
// If it is supported get the addresses of all the APIs here.
#define GET_EXTENSION_ADDRESS(FUNC) \
FUNC = reinterpret_cast<FUNC##_fn>( \
clGetExtensionFunctionAddressForPlatform(platform, #FUNC)); \
if (FUNC == nullptr) \
{ \
log_error("ERROR: clGetExtensionFunctionAddressForPlatform failed" \
" with " #FUNC "\n"); \
return TEST_FAIL; \
}
// Helper test fixture for constructing OpenCL objects used in testing
// a variety of simple command-buffer enqueue scenarios.
struct BasicCommandBufferTest : CommandBufferTestBase
@@ -70,6 +82,7 @@ protected:
clCommandBufferWrapper command_buffer;
};
template <class T>
int MakeAndRunTest(cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements)

View File

@@ -19,17 +19,6 @@
#include "../basic_command_buffer.h"
#include "../command_buffer_test_base.h"
// If it is supported get the addresses of all the APIs here.
#define GET_EXTENSION_ADDRESS(FUNC) \
FUNC = reinterpret_cast<FUNC##_fn>( \
clGetExtensionFunctionAddressForPlatform(platform, #FUNC)); \
if (FUNC == nullptr) \
{ \
log_error("ERROR: clGetExtensionFunctionAddressForPlatform failed" \
" with " #FUNC "\n"); \
return TEST_FAIL; \
}
struct BasicMutableCommandBufferTest : BasicCommandBufferTest
{
BasicMutableCommandBufferTest(cl_device_id device, cl_context context,

View File

@@ -14,6 +14,7 @@
// limitations under the License.
//
#include "basic_command_buffer.h"
#include "svm_command_basic.h"
#include "harness/typeWrappers.h"
#include "procs.h"
@@ -197,6 +198,74 @@ struct CopyBufferKHR : public BasicCommandBufferTest
const cl_char pattern_2 = 0x28;
};
struct CopySVMBufferKHR : public BasicSVMCommandBufferTest
{
using BasicSVMCommandBufferTest::BasicSVMCommandBufferTest;
cl_int Run() override
{
cl_int error = clCommandSVMMemFillKHR(
command_buffer, nullptr, svm_in_mem(), &pattern_1, sizeof(cl_char),
data_size(), 0, nullptr, nullptr, nullptr);
test_error(error, "clCommandSVMMemFillKHR failed");
error = clCommandSVMMemcpyKHR(command_buffer, nullptr, svm_out_mem(),
svm_in_mem(), data_size(), 0, nullptr,
nullptr, nullptr);
test_error(error, "clCommandSVMMemcpyKHR failed");
error = clFinalizeCommandBufferKHR(command_buffer);
test_error(error, "clFinalizeCommandBufferKHR failed");
error = clEnqueueCommandBufferKHR(0, nullptr, command_buffer, 0,
nullptr, nullptr);
test_error(error, "clEnqueueCommandBufferKHR failed");
std::vector<cl_char> output_data_1(data_size());
error =
clEnqueueSVMMemcpy(queue, CL_TRUE, output_data_1.data(),
svm_out_mem(), data_size(), 0, nullptr, nullptr);
test_error(error, "clEnqueueSVMMemcpy failed");
for (size_t i = 0; i < data_size(); i++)
{
CHECK_VERIFICATION_ERROR(pattern_1, output_data_1[i], i);
}
/* Check second enqueue of command buffer */
error = clEnqueueSVMMemFill(queue, svm_in_mem(), &pattern_2,
sizeof(cl_char), data_size(), 0, nullptr,
nullptr);
test_error(error, "clEnqueueSVMMemFill failed");
error = clEnqueueSVMMemFill(queue, svm_out_mem(), &pattern_2,
sizeof(cl_char), data_size(), 0, nullptr,
nullptr);
test_error(error, "clEnqueueSVMMemFill failed");
error = clEnqueueCommandBufferKHR(0, nullptr, command_buffer, 0,
nullptr, nullptr);
test_error(error, "clEnqueueCommandBufferKHR failed");
std::vector<cl_char> output_data_2(data_size());
error =
clEnqueueSVMMemcpy(queue, CL_TRUE, output_data_2.data(),
svm_out_mem(), data_size(), 0, nullptr, nullptr);
test_error(error, "clEnqueueSVMMemcpy failed");
for (size_t i = 0; i < data_size(); i++)
{
CHECK_VERIFICATION_ERROR(pattern_1, output_data_2[i], i);
}
return CL_SUCCESS;
}
const cl_char pattern_1 = 0x14;
const cl_char pattern_2 = 0x28;
};
struct CopyBufferToImageKHR : public BasicCommandBufferTest
{
using BasicCommandBufferTest::BasicCommandBufferTest;
@@ -510,6 +579,14 @@ int test_copy_buffer(cl_device_id device, cl_context context,
return MakeAndRunTest<CopyBufferKHR>(device, context, queue, num_elements);
}
int test_copy_svm_buffer(cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements)
{
return MakeAndRunTest<CopySVMBufferKHR>(device, context, queue,
num_elements);
}
int test_copy_buffer_to_image(cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements)
{

View File

@@ -14,6 +14,7 @@
// limitations under the License.
//
#include "basic_command_buffer.h"
#include "svm_command_basic.h"
#include "harness/typeWrappers.h"
#include "procs.h"
@@ -171,6 +172,64 @@ struct FillBufferKHR : public BasicCommandBufferTest
const char pattern_2 = 0x30;
};
struct FillSVMBufferKHR : public BasicSVMCommandBufferTest
{
using BasicSVMCommandBufferTest::BasicSVMCommandBufferTest;
cl_int Run() override
{
cl_int error = clCommandSVMMemFillKHR(
command_buffer, nullptr, svm_in_mem(), &pattern_1, sizeof(cl_char),
data_size(), 0, nullptr, nullptr, nullptr);
test_error(error, "clCommandSVMMemFillKHR failed");
error = clFinalizeCommandBufferKHR(command_buffer);
test_error(error, "clFinalizeCommandBufferKHR failed");
error = clEnqueueCommandBufferKHR(0, nullptr, command_buffer, 0,
nullptr, nullptr);
test_error(error, "clEnqueueCommandBufferKHR failed");
std::vector<cl_char> output_data_1(data_size());
error =
clEnqueueSVMMemcpy(queue, CL_TRUE, output_data_1.data(),
svm_in_mem(), data_size(), 0, nullptr, nullptr);
test_error(error, "clEnqueueSVMMemcpy failed");
for (size_t i = 0; i < data_size(); i++)
{
CHECK_VERIFICATION_ERROR(pattern_1, output_data_1[i], i);
}
/* Check second enqueue of command buffer */
error = clEnqueueSVMMemFill(queue, svm_in_mem(), &pattern_2,
sizeof(cl_char), data_size(), 0, nullptr,
nullptr);
test_error(error, "clEnqueueSVMMemFill failed");
error = clEnqueueCommandBufferKHR(0, nullptr, command_buffer, 0,
nullptr, nullptr);
test_error(error, "clEnqueueCommandBufferKHR failed");
std::vector<cl_char> output_data_2(data_size());
error =
clEnqueueSVMMemcpy(queue, CL_TRUE, output_data_2.data(),
svm_in_mem(), data_size(), 0, nullptr, nullptr);
test_error(error, "clEnqueueSVMMemcpy failed");
for (size_t i = 0; i < data_size(); i++)
{
CHECK_VERIFICATION_ERROR(pattern_1, output_data_2[i], i);
}
return CL_SUCCESS;
}
const char pattern_1 = 0x15;
const char pattern_2 = 0x30;
};
};
int test_fill_buffer(cl_device_id device, cl_context context,
@@ -179,6 +238,14 @@ int test_fill_buffer(cl_device_id device, cl_context context,
return MakeAndRunTest<FillBufferKHR>(device, context, queue, num_elements);
}
int test_fill_svm_buffer(cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements)
{
return MakeAndRunTest<FillSVMBufferKHR>(device, context, queue,
num_elements);
}
int test_fill_image(cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements)
{

View File

@@ -45,8 +45,10 @@ test_definition test_list[] = {
ADD_TEST(simultaneous_queue_substitution),
ADD_TEST(fill_image),
ADD_TEST(fill_buffer),
ADD_TEST(fill_svm_buffer),
ADD_TEST(copy_image),
ADD_TEST(copy_buffer),
ADD_TEST(copy_svm_buffer),
ADD_TEST(copy_buffer_to_image),
ADD_TEST(copy_image_to_buffer),
ADD_TEST(copy_buffer_rect),

View File

@@ -103,10 +103,14 @@ extern int test_fill_image(cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements);
extern int test_fill_buffer(cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements);
extern int test_fill_svm_buffer(cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements);
extern int test_copy_image(cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements);
extern int test_copy_buffer(cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements);
extern int test_copy_svm_buffer(cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements);
extern int test_copy_buffer_to_image(cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements);
extern int test_copy_image_to_buffer(cl_device_id device, cl_context context,

View File

@@ -0,0 +1,94 @@
//
// Copyright (c) 2023 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 "svm_command_basic.h"
//--------------------------------------------------------------------------
bool BasicSVMCommandBufferTest::Skip()
{
if (BasicCommandBufferTest::Skip()) return true;
Version version = get_device_cl_version(device);
if (version < Version(2, 0))
{
log_info("test requires OpenCL 2.x/3.0 device");
return true;
}
cl_device_svm_capabilities svm_capabilities;
cl_int error =
clGetDeviceInfo(device, CL_DEVICE_SVM_CAPABILITIES,
sizeof(svm_capabilities), &svm_capabilities, NULL);
if (error != CL_SUCCESS)
{
print_error(error, "Unable to query CL_DEVICE_SVM_CAPABILITIES");
return true;
}
if (svm_capabilities == 0)
{
log_info("Device property CL_DEVICE_SVM_COARSE_GRAIN_BUFFER not "
"supported \n");
return true;
}
if (init_extension_functions() != CL_SUCCESS)
{
log_error("Unable to initialise extension functions");
return true;
}
return false;
}
//--------------------------------------------------------------------------
cl_int BasicSVMCommandBufferTest::SetUpKernelArgs(void)
{
size_t size = sizeof(cl_int) * num_elements * buffer_size_multiplier;
svm_in_mem = clSVMWrapper(context, size);
if (svm_in_mem() == nullptr)
{
log_error("Unable to allocate SVM memory");
return CL_OUT_OF_RESOURCES;
}
svm_out_mem = clSVMWrapper(context, size);
if (svm_out_mem() == nullptr)
{
log_error("Unable to allocate SVM memory");
return CL_OUT_OF_RESOURCES;
}
return CL_SUCCESS;
}
//--------------------------------------------------------------------------
cl_int BasicSVMCommandBufferTest::init_extension_functions()
{
cl_int error = BasicCommandBufferTest::init_extension_functions();
test_error(error, "Unable to initialise extension functions");
cl_platform_id platform;
error = clGetDeviceInfo(device, CL_DEVICE_PLATFORM, sizeof(cl_platform_id),
&platform, nullptr);
test_error(error, "clGetDeviceInfo for CL_DEVICE_PLATFORM failed");
GET_EXTENSION_ADDRESS(clCommandSVMMemFillKHR);
GET_EXTENSION_ADDRESS(clCommandSVMMemcpyKHR);
return CL_SUCCESS;
}

View File

@@ -0,0 +1,42 @@
//
// Copyright (c) 2023 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.
//
#ifndef CL_KHR_SVM_COMMAND_BASIC_H
#define CL_KHR_SVM_COMMAND_BASIC_H
#include "basic_command_buffer.h"
struct BasicSVMCommandBufferTest : BasicCommandBufferTest
{
BasicSVMCommandBufferTest(cl_device_id device, cl_context context,
cl_command_queue queue)
: BasicCommandBufferTest(device, context, queue)
{}
virtual bool Skip() override;
virtual cl_int SetUpKernelArgs(void) override;
protected:
cl_int init_extension_functions();
clCommandSVMMemFillKHR_fn clCommandSVMMemFillKHR = nullptr;
clCommandSVMMemcpyKHR_fn clCommandSVMMemcpyKHR = nullptr;
clSVMWrapper svm_in_mem, svm_out_mem;
};
#endif