mirror of
https://github.com/KhronosGroup/OpenCL-CTS.git
synced 2026-03-22 23:29:02 +00:00
Testing Existing SVM APIs remaining APIs tests (#2441)
Tests for the following APIs: * clEnqueueSVMMemcpy * clEnqueueSVMMemFill * clEnqueueSVMMap/clEnqueueSVMUnMap * clEnqueueSVMMigrateMem * clEnqueueSVMMemFree * clSetKernelArgSVMPointer * clSetKernelExecInfo --------- Signed-off-by: John Kesapides <john.kesapides@arm.com>
This commit is contained in:
260
test_conformance/SVM/test_unified_svm_free.cpp
Normal file
260
test_conformance/SVM/test_unified_svm_free.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
//
|
||||
// Copyright (c) 2025 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 "unified_svm_fixture.h"
|
||||
#include "harness/conversions.h"
|
||||
#include "harness/testHarness.h"
|
||||
#include "harness/typeWrappers.h"
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
|
||||
namespace {
|
||||
|
||||
struct CallbackData
|
||||
{
|
||||
CallbackData(cl_context ctx, std::vector<cl_svm_capabilities_khr> &caps)
|
||||
: context{ ctx }, status{ 0 }, svm_pointers{}, svm_caps{ caps }
|
||||
{}
|
||||
cl_context context;
|
||||
std::atomic<cl_uint> status;
|
||||
std::vector<void *> svm_pointers;
|
||||
std::vector<cl_svm_capabilities_khr> &svm_caps;
|
||||
};
|
||||
|
||||
// callback which will be passed to clEnqueueSVMFree command
|
||||
void CL_CALLBACK callback_svm_free(cl_command_queue queue,
|
||||
cl_uint num_svm_pointers,
|
||||
void *svm_pointers[], void *user_data)
|
||||
{
|
||||
auto data = (CallbackData *)user_data;
|
||||
|
||||
data->svm_pointers.resize(num_svm_pointers, 0);
|
||||
|
||||
for (size_t i = 0; i < num_svm_pointers; ++i)
|
||||
{
|
||||
data->svm_pointers[i] = svm_pointers[i];
|
||||
|
||||
if (data->svm_caps[i] & CL_SVM_CAPABILITY_SYSTEM_ALLOCATED_KHR)
|
||||
{
|
||||
align_free(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
clSVMFree(data->context, svm_pointers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
data->status.store(1, std::memory_order_release);
|
||||
}
|
||||
|
||||
void log_error_usvm_ptrs(const std::vector<void *> &v)
|
||||
{
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
{
|
||||
log_error("\t%zu: %p\n", i, v[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct UnifiedSVMFree : UnifiedSVMBase
|
||||
{
|
||||
using UnifiedSVMBase::UnifiedSVMBase;
|
||||
|
||||
// Test the clEnqueueSVMFree function for a vector of USM pointers
|
||||
// and validate the callback.
|
||||
cl_int
|
||||
test_SVMFreeCallback(std::vector<void *> &buffers,
|
||||
std::vector<cl_svm_capabilities_khr> &bufferCaps)
|
||||
{
|
||||
cl_int err = CL_SUCCESS;
|
||||
|
||||
clEventWrapper event;
|
||||
|
||||
CallbackData data{ context, bufferCaps };
|
||||
|
||||
err = clEnqueueSVMFree(queue, buffers.size(), buffers.data(),
|
||||
callback_svm_free, &data, 0, 0, &event);
|
||||
test_error(err, "clEnqueueSVMFree failed");
|
||||
|
||||
err = clFinish(queue);
|
||||
test_error(err, "clFinish failed");
|
||||
|
||||
err = check_event_type(event, CL_COMMAND_SVM_FREE);
|
||||
test_error(err, "Invalid command type returned for clEnqueueSVMFree");
|
||||
|
||||
// wait for the callback
|
||||
while (data.status.load(std::memory_order_acquire) == 0)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(1));
|
||||
}
|
||||
|
||||
// check if pointers returned in callback are correct
|
||||
if (data.svm_pointers != buffers)
|
||||
{
|
||||
log_error("Invalid SVM pointer returned in the callback \n");
|
||||
log_error("Expected:\n");
|
||||
log_error_usvm_ptrs(buffers);
|
||||
log_error("Got:\n");
|
||||
log_error_usvm_ptrs(data.svm_pointers);
|
||||
|
||||
return TEST_FAIL;
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int test_SVMFree(std::vector<void *> &buffers)
|
||||
{
|
||||
cl_int err = CL_SUCCESS;
|
||||
|
||||
clEventWrapper event;
|
||||
|
||||
err = clEnqueueSVMFree(queue, buffers.size(), buffers.data(), nullptr,
|
||||
nullptr, 0, 0, &event);
|
||||
test_error(err, "clEnqueueSVMFree failed");
|
||||
|
||||
err = clFinish(queue);
|
||||
test_error(err, "clFinish failed");
|
||||
|
||||
err = check_event_type(event, CL_COMMAND_SVM_FREE);
|
||||
test_error(err, "Invalid command type returned for clEnqueueSVMFree");
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int run() override
|
||||
{
|
||||
cl_int err;
|
||||
|
||||
// Test clEnqueueSVMFree function with a callback
|
||||
for (int it = 0; it < test_iterations; it++)
|
||||
{
|
||||
std::vector<void *> buffers;
|
||||
std::vector<cl_svm_capabilities_khr> bufferCaps;
|
||||
|
||||
size_t numSVMBuffers = get_random_size_t(1, 20, d);
|
||||
|
||||
for (int i = 0; i < numSVMBuffers; i++)
|
||||
{
|
||||
size_t typeIndex =
|
||||
get_random_size_t(0, deviceUSVMCaps.size() - 1, d);
|
||||
|
||||
auto mem = get_usvm_wrapper<cl_uchar>(typeIndex);
|
||||
|
||||
err = mem->allocate(alloc_count);
|
||||
test_error(err, "SVM allocation failed");
|
||||
|
||||
buffers.push_back(mem->get_ptr());
|
||||
bufferCaps.push_back(deviceUSVMCaps[typeIndex]);
|
||||
|
||||
mem->reset();
|
||||
}
|
||||
|
||||
err = test_SVMFreeCallback(buffers, bufferCaps);
|
||||
test_error(err, "test_SVMFree");
|
||||
}
|
||||
|
||||
// We need to filter out the SVM types that support system allocation
|
||||
// as we cannot test clEnqueueSVMFree without a callback for them
|
||||
std::vector<size_t> test_indexes;
|
||||
for (size_t i = 0; i < deviceUSVMCaps.size(); i++)
|
||||
{
|
||||
auto caps = deviceUSVMCaps[i];
|
||||
if (0 == (caps & CL_SVM_CAPABILITY_SYSTEM_ALLOCATED_KHR))
|
||||
{
|
||||
test_indexes.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (!test_indexes.empty())
|
||||
{
|
||||
// Test clEnqueueSVMFree function with no callback
|
||||
for (int it = 0; it < test_iterations; it++)
|
||||
{
|
||||
std::vector<void *> buffers;
|
||||
|
||||
size_t numSVMBuffers = get_random_size_t(1, 20, d);
|
||||
|
||||
while (buffers.size() != numSVMBuffers)
|
||||
{
|
||||
size_t test_index =
|
||||
get_random_size_t(0, test_indexes.size() - 1, d);
|
||||
size_t typeIndex = test_indexes[test_index];
|
||||
|
||||
auto mem = get_usvm_wrapper<cl_uchar>(typeIndex);
|
||||
|
||||
err = mem->allocate(alloc_count);
|
||||
test_error(err, "SVM allocation failed");
|
||||
|
||||
buffers.push_back(mem->get_ptr());
|
||||
|
||||
mem->reset();
|
||||
}
|
||||
|
||||
err = test_SVMFree(buffers);
|
||||
test_error(err, "test_SVMFree");
|
||||
}
|
||||
}
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
static constexpr size_t alloc_count = 1024;
|
||||
static constexpr size_t test_iterations = 100;
|
||||
};
|
||||
|
||||
REGISTER_TEST(unified_svm_free)
|
||||
{
|
||||
if (!is_extension_available(device, "cl_khr_unified_svm"))
|
||||
{
|
||||
log_info("cl_khr_unified_svm is not supported, skipping test.\n");
|
||||
return TEST_SKIPPED_ITSELF;
|
||||
}
|
||||
|
||||
cl_int err;
|
||||
|
||||
clContextWrapper contextWrapper;
|
||||
clCommandQueueWrapper queueWrapper;
|
||||
|
||||
// For now: create a new context and queue.
|
||||
// If we switch to a new test executable and run the tests without
|
||||
// forceNoContextCreation then this can be removed, and we can just use the
|
||||
// context and the queue from the harness.
|
||||
if (context == nullptr)
|
||||
{
|
||||
contextWrapper =
|
||||
clCreateContext(nullptr, 1, &device, nullptr, nullptr, &err);
|
||||
test_error(err, "clCreateContext failed");
|
||||
context = contextWrapper;
|
||||
}
|
||||
|
||||
if (queue == nullptr)
|
||||
{
|
||||
queueWrapper = clCreateCommandQueue(context, device, 0, &err);
|
||||
test_error(err, "clCreateCommandQueue failed");
|
||||
queue = queueWrapper;
|
||||
}
|
||||
|
||||
UnifiedSVMFree Test(context, device, queue, num_elements);
|
||||
err = Test.setup();
|
||||
test_error(err, "test setup failed");
|
||||
|
||||
err = Test.run();
|
||||
test_error(err, "test failed");
|
||||
|
||||
return TEST_PASS;
|
||||
}
|
||||
Reference in New Issue
Block a user