You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
282 lines
8.9 KiB
282 lines
8.9 KiB
//
|
|
// Copyright (c) 2017 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 "harness/testHarness.h"
|
|
#include "harness/kernelHelpers.h"
|
|
#include "harness/typeWrappers.h"
|
|
|
|
#include "common.h"
|
|
|
|
const char *get_memory_order_type_name(TExplicitMemoryOrderType orderType)
|
|
{
|
|
switch (orderType)
|
|
{
|
|
case MEMORY_ORDER_EMPTY:
|
|
return "";
|
|
case MEMORY_ORDER_RELAXED:
|
|
return "memory_order_relaxed";
|
|
case MEMORY_ORDER_ACQUIRE:
|
|
return "memory_order_acquire";
|
|
case MEMORY_ORDER_RELEASE:
|
|
return "memory_order_release";
|
|
case MEMORY_ORDER_ACQ_REL:
|
|
return "memory_order_acq_rel";
|
|
case MEMORY_ORDER_SEQ_CST:
|
|
return "memory_order_seq_cst";
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
const char *get_memory_scope_type_name(TExplicitMemoryScopeType scopeType)
|
|
{
|
|
switch (scopeType)
|
|
{
|
|
case MEMORY_SCOPE_EMPTY: return "";
|
|
case MEMORY_SCOPE_WORK_GROUP: return "memory_scope_work_group";
|
|
case MEMORY_SCOPE_DEVICE: return "memory_scope_device";
|
|
case MEMORY_SCOPE_ALL_DEVICES: return "memory_scope_all_devices";
|
|
case MEMORY_SCOPE_ALL_SVM_DEVICES: return "memory_scope_all_svm_devices";
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
|
|
cl_uint AtomicTypeInfo::Size(cl_device_id device)
|
|
{
|
|
switch(_type)
|
|
{
|
|
case TYPE_ATOMIC_INT:
|
|
case TYPE_ATOMIC_UINT:
|
|
case TYPE_ATOMIC_FLOAT:
|
|
case TYPE_ATOMIC_FLAG:
|
|
return sizeof(cl_int);
|
|
case TYPE_ATOMIC_LONG:
|
|
case TYPE_ATOMIC_ULONG:
|
|
case TYPE_ATOMIC_DOUBLE:
|
|
return sizeof(cl_long);
|
|
case TYPE_ATOMIC_INTPTR_T:
|
|
case TYPE_ATOMIC_UINTPTR_T:
|
|
case TYPE_ATOMIC_SIZE_T:
|
|
case TYPE_ATOMIC_PTRDIFF_T:
|
|
{
|
|
int error;
|
|
cl_uint addressBits = 0;
|
|
|
|
error = clGetDeviceInfo(device, CL_DEVICE_ADDRESS_BITS, sizeof(addressBits), &addressBits, 0);
|
|
test_error_ret(error, "clGetDeviceInfo", 0);
|
|
|
|
return addressBits/8;
|
|
}
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
const char *AtomicTypeInfo::AtomicTypeName()
|
|
{
|
|
switch(_type)
|
|
{
|
|
case TYPE_ATOMIC_INT:
|
|
return "atomic_int";
|
|
case TYPE_ATOMIC_UINT:
|
|
return "atomic_uint";
|
|
case TYPE_ATOMIC_FLOAT:
|
|
return "atomic_float";
|
|
case TYPE_ATOMIC_FLAG:
|
|
return "atomic_flag";
|
|
case TYPE_ATOMIC_LONG:
|
|
return "atomic_long";
|
|
case TYPE_ATOMIC_ULONG:
|
|
return "atomic_ulong";
|
|
case TYPE_ATOMIC_DOUBLE:
|
|
return "atomic_double";
|
|
case TYPE_ATOMIC_INTPTR_T:
|
|
return "atomic_intptr_t";
|
|
case TYPE_ATOMIC_UINTPTR_T:
|
|
return "atomic_uintptr_t";
|
|
case TYPE_ATOMIC_SIZE_T:
|
|
return "atomic_size_t";
|
|
case TYPE_ATOMIC_PTRDIFF_T:
|
|
return "atomic_ptrdiff_t";
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
const char *AtomicTypeInfo::RegularTypeName()
|
|
{
|
|
switch(_type)
|
|
{
|
|
case TYPE_ATOMIC_INT:
|
|
return "int";
|
|
case TYPE_ATOMIC_UINT:
|
|
return "uint";
|
|
case TYPE_ATOMIC_FLOAT:
|
|
return "float";
|
|
case TYPE_ATOMIC_FLAG:
|
|
return "int";
|
|
case TYPE_ATOMIC_LONG:
|
|
return "long";
|
|
case TYPE_ATOMIC_ULONG:
|
|
return "ulong";
|
|
case TYPE_ATOMIC_DOUBLE:
|
|
return "double";
|
|
case TYPE_ATOMIC_INTPTR_T:
|
|
return "intptr_t";
|
|
case TYPE_ATOMIC_UINTPTR_T:
|
|
return "uintptr_t";
|
|
case TYPE_ATOMIC_SIZE_T:
|
|
return "size_t";
|
|
case TYPE_ATOMIC_PTRDIFF_T:
|
|
return "ptrdiff_t";
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
const char *AtomicTypeInfo::AddSubOperandTypeName()
|
|
{
|
|
switch(_type)
|
|
{
|
|
case TYPE_ATOMIC_INTPTR_T:
|
|
case TYPE_ATOMIC_UINTPTR_T:
|
|
return AtomicTypeInfo(TYPE_ATOMIC_PTRDIFF_T).RegularTypeName();
|
|
default:
|
|
return RegularTypeName();
|
|
}
|
|
}
|
|
|
|
int AtomicTypeInfo::IsSupported(cl_device_id device)
|
|
{
|
|
switch(_type)
|
|
{
|
|
case TYPE_ATOMIC_INT:
|
|
case TYPE_ATOMIC_UINT:
|
|
case TYPE_ATOMIC_FLOAT:
|
|
case TYPE_ATOMIC_FLAG:
|
|
return 1;
|
|
case TYPE_ATOMIC_LONG:
|
|
case TYPE_ATOMIC_ULONG:
|
|
return is_extension_available(device, "cl_khr_int64_base_atomics") &&
|
|
is_extension_available(device, "cl_khr_int64_extended_atomics");
|
|
case TYPE_ATOMIC_DOUBLE:
|
|
return is_extension_available(device, "cl_khr_int64_base_atomics") &&
|
|
is_extension_available(device, "cl_khr_int64_extended_atomics") &&
|
|
is_extension_available(device, "cl_khr_fp64");
|
|
case TYPE_ATOMIC_INTPTR_T:
|
|
case TYPE_ATOMIC_UINTPTR_T:
|
|
case TYPE_ATOMIC_SIZE_T:
|
|
case TYPE_ATOMIC_PTRDIFF_T:
|
|
if(Size(device) == 4)
|
|
return 1;
|
|
return is_extension_available(device, "cl_khr_int64_base_atomics") &&
|
|
is_extension_available(device, "cl_khr_int64_extended_atomics");
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
template<> cl_int AtomicTypeExtendedInfo<cl_int>::MinValue() {return CL_INT_MIN;}
|
|
template<> cl_uint AtomicTypeExtendedInfo<cl_uint>::MinValue() {return 0;}
|
|
template<> cl_long AtomicTypeExtendedInfo<cl_long>::MinValue() {return CL_LONG_MIN;}
|
|
template<> cl_ulong AtomicTypeExtendedInfo<cl_ulong>::MinValue() {return 0;}
|
|
template<> cl_float AtomicTypeExtendedInfo<cl_float>::MinValue() {return CL_FLT_MIN;}
|
|
template<> cl_double AtomicTypeExtendedInfo<cl_double>::MinValue() {return CL_DBL_MIN;}
|
|
|
|
template<> cl_int AtomicTypeExtendedInfo<cl_int>::MaxValue() {return CL_INT_MAX;}
|
|
template<> cl_uint AtomicTypeExtendedInfo<cl_uint>::MaxValue() {return CL_UINT_MAX;}
|
|
template<> cl_long AtomicTypeExtendedInfo<cl_long>::MaxValue() {return CL_LONG_MAX;}
|
|
template<> cl_ulong AtomicTypeExtendedInfo<cl_ulong>::MaxValue() {return CL_ULONG_MAX;}
|
|
template<> cl_float AtomicTypeExtendedInfo<cl_float>::MaxValue() {return CL_FLT_MAX;}
|
|
template<> cl_double AtomicTypeExtendedInfo<cl_double>::MaxValue() {return CL_DBL_MAX;}
|
|
|
|
cl_int getSupportedMemoryOrdersAndScopes(
|
|
cl_device_id device, std::vector<TExplicitMemoryOrderType> &memoryOrders,
|
|
std::vector<TExplicitMemoryScopeType> &memoryScopes)
|
|
{
|
|
// The CL_DEVICE_ATOMIC_MEMORY_CAPABILITES is missing before 3.0, but since
|
|
// all orderings and scopes are required for 2.X devices and this test is
|
|
// skipped before 2.0 we can safely return all orderings and scopes if the
|
|
// device is 2.X. Query device for the supported orders.
|
|
if (get_device_cl_version(device) < Version{ 3, 0 })
|
|
{
|
|
memoryOrders.push_back(MEMORY_ORDER_EMPTY);
|
|
memoryOrders.push_back(MEMORY_ORDER_RELAXED);
|
|
memoryOrders.push_back(MEMORY_ORDER_ACQUIRE);
|
|
memoryOrders.push_back(MEMORY_ORDER_RELEASE);
|
|
memoryOrders.push_back(MEMORY_ORDER_ACQ_REL);
|
|
memoryOrders.push_back(MEMORY_ORDER_SEQ_CST);
|
|
memoryScopes.push_back(MEMORY_SCOPE_EMPTY);
|
|
memoryScopes.push_back(MEMORY_SCOPE_WORK_GROUP);
|
|
memoryScopes.push_back(MEMORY_SCOPE_DEVICE);
|
|
memoryScopes.push_back(MEMORY_SCOPE_ALL_SVM_DEVICES);
|
|
return CL_SUCCESS;
|
|
}
|
|
|
|
// For a 3.0 device we can query the supported orderings and scopes
|
|
// directly.
|
|
cl_device_atomic_capabilities atomic_capabilities{};
|
|
test_error(
|
|
clGetDeviceInfo(device, CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES,
|
|
sizeof(atomic_capabilities), &atomic_capabilities,
|
|
nullptr),
|
|
"clGetDeviceInfo failed for CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES\n");
|
|
|
|
// Provided we succeeded, we can start filling the vectors.
|
|
if (atomic_capabilities & CL_DEVICE_ATOMIC_ORDER_RELAXED)
|
|
{
|
|
memoryOrders.push_back(MEMORY_ORDER_RELAXED);
|
|
}
|
|
|
|
if (atomic_capabilities & CL_DEVICE_ATOMIC_ORDER_ACQ_REL)
|
|
{
|
|
memoryOrders.push_back(MEMORY_ORDER_ACQUIRE);
|
|
memoryOrders.push_back(MEMORY_ORDER_RELEASE);
|
|
memoryOrders.push_back(MEMORY_ORDER_ACQ_REL);
|
|
}
|
|
|
|
if (atomic_capabilities & CL_DEVICE_ATOMIC_ORDER_SEQ_CST)
|
|
{
|
|
// The functions not ending in explicit have the same semantics as the
|
|
// corresponding explicit function with memory_order_seq_cst for the
|
|
// memory_order argument.
|
|
memoryOrders.push_back(MEMORY_ORDER_EMPTY);
|
|
memoryOrders.push_back(MEMORY_ORDER_SEQ_CST);
|
|
}
|
|
|
|
if (atomic_capabilities & CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP)
|
|
{
|
|
memoryScopes.push_back(MEMORY_SCOPE_WORK_GROUP);
|
|
}
|
|
|
|
if (atomic_capabilities & CL_DEVICE_ATOMIC_SCOPE_DEVICE)
|
|
{
|
|
// The functions that do not have memory_scope argument have the same
|
|
// semantics as the corresponding functions with the memory_scope
|
|
// argument set to memory_scope_device.
|
|
memoryScopes.push_back(MEMORY_SCOPE_EMPTY);
|
|
memoryScopes.push_back(MEMORY_SCOPE_DEVICE);
|
|
}
|
|
if (atomic_capabilities & CL_DEVICE_ATOMIC_SCOPE_ALL_DEVICES)
|
|
{
|
|
// OpenCL 3.0 added memory_scope_all_devices as an alias for
|
|
// memory_scope_all_svm_devices, so test both.
|
|
memoryScopes.push_back(MEMORY_SCOPE_ALL_DEVICES);
|
|
memoryScopes.push_back(MEMORY_SCOPE_ALL_SVM_DEVICES);
|
|
}
|
|
return CL_SUCCESS;
|
|
}
|