Commit 51ab3dc3 by John Plate Committed by Angle LUCI CQ

CL: Improve validation readablity

Improve validation readablity by introducing a bit field class and by changing how the CL error code is returned. Bug: angleproject:6001 Change-Id: I51deb745454e5281de725481edef85eb30be28c7 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2919690Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com> Commit-Queue: John Plate <jplate@google.com>
parent 4796e452
......@@ -10,7 +10,7 @@
"scripts/entry_point_packed_gl_enums.json":
"4f7b43863a5e61991bba4010db463679",
"scripts/generate_entry_points.py":
"e188b924a861e07840c39399e6826dd6",
"a2675710977baeb42b33ec28f2a5ed3b",
"scripts/gl.xml":
"2a73a58a7e26d8676a2c0af6d528cae6",
"scripts/gl_angle_ext.xml":
......@@ -74,7 +74,7 @@
"src/libANGLE/capture/frame_capture_utils_autogen.h":
"4405cac61b4f79b893bd40c7fc452397",
"src/libANGLE/validationCL_autogen.h":
"605034156dbc715aeac197c7db56c684",
"0022d0cdb6a9e2ef4a59b71164f62333",
"src/libANGLE/validationEGL_autogen.h":
"3927fa260ad183fd9193d65b3f8d82c5",
"src/libANGLE/validationES1_autogen.h":
......@@ -122,7 +122,7 @@
"src/libGL/libGL_autogen.def":
"2789d87b05eea9f53d52e2aff499b785",
"src/libGLESv2/cl_stubs_autogen.h":
"90fd22a3e8665b3f9ff807db8ffedf0d",
"6d880c6b65284192b5842f0e42ad2741",
"src/libGLESv2/egl_ext_stubs_autogen.h":
"2ef3b8d087f2a97f7270b96077c93856",
"src/libGLESv2/egl_get_labeled_object_data.json":
......@@ -130,7 +130,7 @@
"src/libGLESv2/egl_stubs_autogen.h":
"6439daa350c1663e71dd0af37dcc91df",
"src/libGLESv2/entry_points_cl_autogen.cpp":
"858f3c2bf35186a82d4bae4129926aa8",
"23810a61bbc63bd908d96549b033dce9",
"src/libGLESv2/entry_points_cl_autogen.h":
"dde2f94c3004874a7da995dae69da811",
"src/libGLESv2/entry_points_egl_autogen.cpp":
......
......@@ -284,6 +284,30 @@ cl_int CL_API_CALL cl{name}({params})
}}
"""
TEMPLATE_CL_ENTRY_POINT_WITH_ERRCODE_RET = """\
{return_type} CL_API_CALL cl{name}({params})
{{
ANGLE_SCOPED_GLOBAL_LOCK();
{initialization}
CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
{packed_gl_enum_conversions}
ANGLE_CL_VALIDATE_ERRCODE_RET({name}{comma_if_needed}{internal_params});
cl_int errorCode = CL_SUCCESS;
{return_type} object = {name}({internal_params}, errorCode);
ASSERT((errorCode == CL_SUCCESS) == (object != nullptr));
if (errcode_ret != nullptr)
{{
*errcode_ret = errorCode;
}}
return object;
}}
"""
TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_POINTER = """\
{return_type} CL_API_CALL cl{name}({params})
{{
......@@ -1216,6 +1240,20 @@ CL_PACKED_TYPES = {
"cl_kernel_exec_info": "KernelExecInfo",
"cl_event_info": "EventInfo",
"cl_profiling_info": "ProfilingInfo",
# Bit fields
"cl_device_type": "DeviceType",
"cl_device_fp_config": "DeviceFpConfig",
"cl_device_exec_capabilities": "DeviceExecCapabilities",
"cl_device_svm_capabilities": "DeviceSvmCapabilities",
"cl_command_queue_properties": "CommandQueueProperties",
"cl_device_affinity_domain": "DeviceAffinityDomain",
"cl_mem_flags": "MemFlags",
"cl_svm_mem_flags": "SVM_MemFlags",
"cl_mem_migration_flags": "MemMigrationFlags",
"cl_map_flags": "MapFlags",
"cl_kernel_arg_type_qualifier": "KernelArgTypeQualifier",
"cl_device_atomic_capabilities": "DeviceAtomicCapabilities",
"cl_device_device_enqueue_capabilities": "DeviceEnqueueCapabilities",
}
EGL_PACKED_TYPES = {
......@@ -1481,7 +1519,7 @@ def get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types, par
return result
def get_def_template(api, return_type):
def get_def_template(api, return_type, has_errcode_ret):
if return_type == "void":
if api == apis.EGL:
return TEMPLATE_EGL_ENTRY_POINT_NO_RETURN
......@@ -1495,7 +1533,10 @@ def get_def_template(api, return_type):
if api == apis.EGL:
return TEMPLATE_EGL_ENTRY_POINT_WITH_RETURN
elif api == apis.CL:
return TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_POINTER
if has_errcode_ret:
return TEMPLATE_CL_ENTRY_POINT_WITH_ERRCODE_RET
else:
return TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_POINTER
else:
return TEMPLATE_GLES_ENTRY_POINT_WITH_RETURN
......@@ -1504,6 +1545,11 @@ def format_entry_point_def(api, command_node, cmd_name, proto, params, is_explic
cmd_packed_enums, packed_param_types, ep_to_object):
packed_enums = get_packed_enums(api, cmd_packed_enums, cmd_name, packed_param_types, params)
internal_params = [just_the_name_packed(param, packed_enums) for param in params]
if internal_params and internal_params[-1] == "errcode_ret":
internal_params.pop()
has_errcode_ret = True
else:
has_errcode_ret = False
packed_gl_enum_conversions = []
for param in params:
name = just_the_name(param)
......@@ -1565,7 +1611,7 @@ def format_entry_point_def(api, command_node, cmd_name, proto, params, is_explic
get_egl_entry_point_labeled_object(ep_to_object, cmd_name, params, packed_enums)
}
template = get_def_template(api, return_type)
template = get_def_template(api, return_type, has_errcode_ret)
return template.format(**format_params)
......@@ -1674,10 +1720,11 @@ def get_internal_params(api, cmd_name, params, cmd_packed_gl_enums, packed_param
def get_validation_params(api, cmd_name, params, cmd_packed_gl_enums, packed_param_types):
packed_gl_enums = get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types,
params)
last = -1 if params and just_the_name(params[-1]) == "errcode_ret" else None
return ", ".join([
make_param(
const_pointer_type(param, packed_gl_enums), just_the_name_packed(
param, packed_gl_enums)) for param in params
const_pointer_type(param, packed_gl_enums),
just_the_name_packed(param, packed_gl_enums)) for param in params[:last]
])
......@@ -1716,7 +1763,7 @@ def format_entry_point_export(cmd_name, proto, params, is_explicit_context, temp
def format_validation_proto(api, cmd_name, proto, params, cmd_packed_gl_enums, packed_param_types):
if api == apis.CL:
return_type = "cl_int" if proto[:-len(cmd_name)].strip() == "cl_int" else "bool"
return_type = "cl_int"
else:
return_type = "bool"
if api in [apis.GL, apis.GLES]:
......@@ -2484,9 +2531,9 @@ def write_stubs_header(api, annotation, title, data_source, out_file, all_comman
proto_text = "".join(proto.itertext())
params = [] if api == apis.CL else ["Thread *thread"]
params += ["".join(param.itertext()) for param in command.findall('param')]
if params and just_the_name(params[-1]) == "errcode_ret":
params[-1] = "cl_int &errorCode"
return_type = proto_text[:-len(cmd_name)].strip()
if api == apis.CL and return_type in packed_param_types:
return_type = packed_param_types[return_type]
internal_params = get_internal_params(api, cmd_name, params, cmd_packed_egl_enums,
packed_param_types)
......
//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CLBitField.h: A bit field class that encapsulates the cl_bitfield type.
#ifndef LIBANGLE_CLBITFIELD_H_
#define LIBANGLE_CLBITFIELD_H_
#include <angle_cl.h>
namespace cl
{
class BitField
{
public:
BitField() noexcept : mBits(0u) {}
explicit BitField(cl_bitfield bits) noexcept : mBits(bits) {}
BitField &operator=(cl_bitfield bits)
{
mBits = bits;
return *this;
}
bool operator==(cl_bitfield bits) const { return mBits == bits; }
bool operator!=(cl_bitfield bits) const { return mBits != bits; }
bool operator==(const BitField &other) const { return mBits == other.mBits; }
bool operator!=(const BitField &other) const { return mBits != other.mBits; }
cl_bitfield get() const { return mBits; }
bool isSet(cl_bitfield bits) const { return (mBits & bits) != 0u; }
bool isSet(const BitField &other) const { return (mBits & other.mBits) != 0u; }
bool isNotSet(cl_bitfield bits) const { return (mBits & bits) == 0u; }
bool isNotSet(const BitField &other) const { return (mBits & other.mBits) == 0u; }
bool hasOtherBitsThan(cl_bitfield bits) const { return (mBits & ~bits) != 0u; }
bool hasOtherBitsThan(const BitField &other) const { return (mBits & ~other.mBits) != 0u; }
bool areMutuallyExclusive(cl_bitfield bits1, cl_bitfield bits2) const
{
return (isSet(bits1) ? 1 : 0) + (isSet(bits2) ? 1 : 0) <= 1;
}
bool areMutuallyExclusive(cl_bitfield bits1, cl_bitfield bits2, cl_bitfield bits3) const
{
return (isSet(bits1) ? 1 : 0) + (isSet(bits2) ? 1 : 0) + (isSet(bits3) ? 1 : 0) <= 1;
}
void set(cl_bitfield bits) { mBits |= bits; }
void set(const BitField &other) { mBits |= other.mBits; }
void clear(cl_bitfield bits) { mBits &= ~bits; }
void clear(const BitField &other) { mBits &= ~other.mBits; }
private:
cl_bitfield mBits;
};
static_assert(sizeof(BitField) == sizeof(cl_bitfield), "Type size mismatch");
using DeviceType = BitField;
using DeviceFpConfig = BitField;
using DeviceExecCapabilities = BitField;
using DeviceSvmCapabilities = BitField;
using CommandQueueProperties = BitField;
using DeviceAffinityDomain = BitField;
using MemFlags = BitField;
using SVM_MemFlags = BitField;
using MemMigrationFlags = BitField;
using MapFlags = BitField;
using KernelArgTypeQualifier = BitField;
using DeviceAtomicCapabilities = BitField;
using DeviceEnqueueCapabilities = BitField;
} // namespace cl
#endif // LIBANGLE_CLBITFIELD_H_
......@@ -14,27 +14,26 @@ namespace cl
Buffer::~Buffer() = default;
cl_mem Buffer::createSubBuffer(cl_mem_flags flags,
cl_mem Buffer::createSubBuffer(MemFlags flags,
cl_buffer_create_type createType,
const void *createInfo,
cl_int *errcodeRet)
cl_int &errorCode)
{
const cl_buffer_region &region = *static_cast<const cl_buffer_region *>(createInfo);
return mContext->createMemory(new Buffer(*this, flags, region.origin, region.size, errcodeRet),
errcodeRet);
return mContext->createMemory(new Buffer(*this, flags, region.origin, region.size, errorCode));
}
Buffer::Buffer(Context &context,
PropArray &&properties,
cl_mem_flags flags,
MemFlags flags,
size_t size,
void *hostPtr,
cl_int *errcodeRet)
: Memory(*this, context, std::move(properties), flags, size, hostPtr, errcodeRet)
cl_int &errorCode)
: Memory(*this, context, std::move(properties), flags, size, hostPtr, errorCode)
{}
Buffer::Buffer(Buffer &parent, cl_mem_flags flags, size_t offset, size_t size, cl_int *errcodeRet)
: Memory(*this, parent, flags, offset, size, errcodeRet)
Buffer::Buffer(Buffer &parent, MemFlags flags, size_t offset, size_t size, cl_int &errorCode)
: Memory(*this, parent, flags, offset, size, errorCode)
{}
} // namespace cl
......@@ -23,22 +23,22 @@ class Buffer final : public Memory
bool isSubBuffer() const;
bool isRegionValid(const cl_buffer_region &region) const;
cl_mem createSubBuffer(cl_mem_flags flags,
cl_mem createSubBuffer(MemFlags flags,
cl_buffer_create_type createType,
const void *createInfo,
cl_int *errcodeRet);
cl_int &errorCode);
static bool IsValid(const _cl_mem *buffer);
private:
Buffer(Context &context,
PropArray &&properties,
cl_mem_flags flags,
MemFlags flags,
size_t size,
void *hostPtr,
cl_int *errcodeRet);
cl_int &errorCode);
Buffer(Buffer &parent, cl_mem_flags flags, size_t offset, size_t size, cl_int *errcodeRet);
Buffer(Buffer &parent, MemFlags flags, size_t offset, size_t size, cl_int &errorCode);
friend class Context;
};
......@@ -50,7 +50,7 @@ inline cl_mem_object_type Buffer::getType() const
inline bool Buffer::isSubBuffer() const
{
return bool(mParent);
return mParent.isValid();
}
inline bool Buffer::isRegionValid(const cl_buffer_region &region) const
......
......@@ -82,6 +82,8 @@ cl_int CommandQueue::getInfo(CommandQueueInfo name,
if (value != nullptr)
{
// CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
// as specified in the Command Queue Parameter table, and param_value is not a NULL value.
if (valueSize < copySize)
{
return CL_INVALID_VALUE;
......@@ -98,24 +100,24 @@ cl_int CommandQueue::getInfo(CommandQueueInfo name,
return CL_SUCCESS;
}
cl_int CommandQueue::setProperty(cl_command_queue_properties properties,
cl_int CommandQueue::setProperty(CommandQueueProperties properties,
cl_bool enable,
cl_command_queue_properties *oldProperties)
{
if (oldProperties != nullptr)
{
*oldProperties = mProperties;
*oldProperties = mProperties.get();
}
const cl_int result = mImpl->setProperty(properties, enable);
if (result == CL_SUCCESS)
{
if (enable == CL_FALSE)
{
mProperties &= ~properties;
mProperties.clear(properties);
}
else
{
mProperties |= properties;
mProperties.set(properties);
}
}
return result;
......@@ -131,30 +133,30 @@ bool CommandQueue::IsValid(const _cl_command_queue *commandQueue)
CommandQueue::CommandQueue(Context &context,
Device &device,
cl_command_queue_properties properties,
cl_int *errcodeRet)
CommandQueueProperties properties,
cl_int &errorCode)
: _cl_command_queue(context.getDispatch()),
mContext(&context),
mDevice(&device),
mProperties(properties),
mImpl(context.mImpl->createCommandQueue(*this, errcodeRet))
mImpl(context.mImpl->createCommandQueue(*this, errorCode))
{}
CommandQueue::CommandQueue(Context &context,
Device &device,
PropArray &&propArray,
cl_command_queue_properties properties,
CommandQueueProperties properties,
cl_uint size,
cl_int *errcodeRet)
cl_int &errorCode)
: _cl_command_queue(context.getDispatch()),
mContext(&context),
mDevice(&device),
mPropArray(std::move(propArray)),
mProperties(properties),
mSize(size),
mImpl(context.mImpl->createCommandQueue(*this, errcodeRet))
mImpl(context.mImpl->createCommandQueue(*this, errorCode))
{
if ((mProperties & CL_QUEUE_ON_DEVICE_DEFAULT) != 0u)
if (mProperties.isSet(CL_QUEUE_ON_DEVICE_DEFAULT))
{
mDevice->mDefaultCommandQueue = this;
}
......
......@@ -30,7 +30,7 @@ class CommandQueue final : public _cl_command_queue, public Object
const Context &getContext() const;
const Device &getDevice() const;
cl_command_queue_properties getProperties() const;
CommandQueueProperties getProperties() const;
bool hasSize() const;
cl_uint getSize() const;
......@@ -42,7 +42,7 @@ class CommandQueue final : public _cl_command_queue, public Object
void *value,
size_t *valueSizeRet) const;
cl_int setProperty(cl_command_queue_properties properties,
cl_int setProperty(CommandQueueProperties properties,
cl_bool enable,
cl_command_queue_properties *oldProperties);
......@@ -51,20 +51,20 @@ class CommandQueue final : public _cl_command_queue, public Object
private:
CommandQueue(Context &context,
Device &device,
cl_command_queue_properties properties,
cl_int *errcodeRet);
CommandQueueProperties properties,
cl_int &errorCode);
CommandQueue(Context &context,
Device &device,
PropArray &&propArray,
cl_command_queue_properties properties,
CommandQueueProperties properties,
cl_uint size,
cl_int *errcodeRet);
cl_int &errorCode);
const ContextRefPtr mContext;
const DeviceRefPtr mDevice;
const PropArray mPropArray;
cl_command_queue_properties mProperties;
CommandQueueProperties mProperties;
const cl_uint mSize = kNoSize;
const rx::CLCommandQueueImpl::Ptr mImpl;
......@@ -81,7 +81,7 @@ inline const Device &CommandQueue::getDevice() const
return *mDevice;
}
inline cl_command_queue_properties CommandQueue::getProperties() const
inline CommandQueueProperties CommandQueue::getProperties() const
{
return mProperties;
}
......
......@@ -46,35 +46,35 @@ class Context final : public _cl_context, public Object
cl_int getInfo(ContextInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const;
cl_command_queue createCommandQueue(cl_device_id device,
cl_command_queue_properties properties,
cl_int *errcodeRet);
CommandQueueProperties properties,
cl_int &errorCode);
cl_command_queue createCommandQueueWithProperties(cl_device_id device,
const cl_queue_properties *properties,
cl_int *errcodeRet);
cl_int &errorCode);
cl_mem createBuffer(const cl_mem_properties *properties,
cl_mem_flags flags,
MemFlags flags,
size_t size,
void *hostPtr,
cl_int *errcodeRet);
cl_int &errorCode);
cl_mem createImage(const cl_mem_properties *properties,
cl_mem_flags flags,
MemFlags flags,
const cl_image_format *format,
const cl_image_desc *desc,
void *hostPtr,
cl_int *errcodeRet);
cl_int &errorCode);
cl_mem createImage2D(cl_mem_flags flags,
cl_mem createImage2D(MemFlags flags,
const cl_image_format *format,
size_t width,
size_t height,
size_t rowPitch,
void *hostPtr,
cl_int *errcodeRet);
cl_int &errorCode);
cl_mem createImage3D(cl_mem_flags flags,
cl_mem createImage3D(MemFlags flags,
const cl_image_format *format,
size_t width,
size_t height,
......@@ -82,36 +82,42 @@ class Context final : public _cl_context, public Object
size_t rowPitch,
size_t slicePitch,
void *hostPtr,
cl_int *errcodeRet);
cl_int &errorCode);
cl_sampler createSampler(cl_bool normalizedCoords,
AddressingMode addressingMode,
FilterMode filterMode,
cl_int *errcodeRet);
cl_int &errorCode);
cl_sampler createSamplerWithProperties(const cl_sampler_properties *properties,
cl_int *errcodeRet);
cl_int &errorCode);
cl_program createProgramWithSource(cl_uint count,
const char **strings,
const size_t *lengths,
cl_int *errcodeRet);
cl_int &errorCode);
cl_program createProgramWithIL(const void *il, size_t length, cl_int *errcodeRet);
cl_program createProgramWithIL(const void *il, size_t length, cl_int &errorCode);
cl_program createProgramWithBinary(cl_uint numDevices,
const cl_device_id *devices,
const size_t *lengths,
const unsigned char **binaries,
cl_int *binaryStatus,
cl_int *errcodeRet);
cl_int &errorCode);
cl_program createProgramWithBuiltInKernels(cl_uint numDevices,
const cl_device_id *devices,
const char *kernelNames,
cl_int *errcodeRet);
cl_int &errorCode);
static bool IsValid(const _cl_context *context);
static bool IsValidAndVersionOrNewer(const _cl_context *context, cl_uint major, cl_uint minor);
static void CL_CALLBACK ErrorCallback(const char *errinfo,
const void *privateInfo,
size_t cb,
void *userData);
private:
Context(Platform &platform,
......@@ -120,37 +126,32 @@ class Context final : public _cl_context, public Object
ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet);
cl_int &errorCode);
Context(Platform &platform,
PropArray &&properties,
cl_device_type deviceType,
DeviceType deviceType,
ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet);
cl_int &errorCode);
cl_command_queue createCommandQueue(CommandQueue *commandQueue, cl_int *errcodeRet);
cl_mem createMemory(Memory *memory, cl_int *errcodeRet);
cl_sampler createSampler(Sampler *sampler, cl_int *errcodeRet);
cl_program createProgram(Program *program, cl_int *errcodeRet);
cl_command_queue createCommandQueue(CommandQueue *commandQueue);
cl_mem createMemory(Memory *memory);
cl_sampler createSampler(Sampler *sampler);
cl_program createProgram(Program *program);
void destroyCommandQueue(CommandQueue *commandQueue);
void destroyMemory(Memory *memory);
void destroySampler(Sampler *sampler);
void destroyProgram(Program *program);
static void CL_CALLBACK ErrorCallback(const char *errinfo,
const void *privateInfo,
size_t cb,
void *userData);
Platform &mPlatform;
const rx::CLContextImpl::Ptr mImpl;
const PropArray mProperties;
const DeviceRefList mDevices;
const ContextErrorCB mNotify;
void *const mUserData;
const rx::CLContextImpl::Ptr mImpl;
const DeviceRefList mDevices;
CommandQueue::PtrList mCommandQueues;
Memory::PtrList mMemories;
......
......@@ -111,13 +111,10 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
case DeviceInfo::NativeVectorWidthHalf:
case DeviceInfo::MaxClockFrequency:
case DeviceInfo::AddressBits:
case DeviceInfo::ImageSupport:
case DeviceInfo::MaxReadImageArgs:
case DeviceInfo::MaxWriteImageArgs:
case DeviceInfo::MaxReadWriteImageArgs:
case DeviceInfo::MaxSamplers:
case DeviceInfo::ImagePitchAlignment:
case DeviceInfo::ImageBaseAddressAlignment:
case DeviceInfo::MaxPipeArgs:
case DeviceInfo::PipeMaxActiveReservations:
case DeviceInfo::PipeMaxPacketSize:
......@@ -134,7 +131,6 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
case DeviceInfo::CompilerAvailable:
case DeviceInfo::LinkerAvailable:
case DeviceInfo::QueueOnDevicePreferredSize:
case DeviceInfo::QueueOnDeviceMaxSize:
case DeviceInfo::MaxOnDeviceQueues:
case DeviceInfo::MaxOnDeviceEvents:
case DeviceInfo::PreferredInteropUserSync:
......@@ -176,13 +172,6 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
// Handle all size_t and aliased types
case DeviceInfo::MaxWorkGroupSize:
case DeviceInfo::Image2D_MaxWidth:
case DeviceInfo::Image2D_MaxHeight:
case DeviceInfo::Image3D_MaxWidth:
case DeviceInfo::Image3D_MaxHeight:
case DeviceInfo::Image3D_MaxDepth:
case DeviceInfo::ImageMaxBufferSize:
case DeviceInfo::ImageMaxArraySize:
case DeviceInfo::MaxParameterSize:
case DeviceInfo::MaxGlobalVariableSize:
case DeviceInfo::GlobalVariablePreferredTotalSize:
......@@ -230,6 +219,10 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
copyValue = &mInfo.mMaxMemAllocSize;
copySize = sizeof(mInfo.mMaxMemAllocSize);
break;
case DeviceInfo::ImageSupport:
copyValue = &mInfo.mImageSupport;
copySize = sizeof(mInfo.mImageSupport);
break;
case DeviceInfo::IL_Version:
copyValue = mInfo.mIL_Version.c_str();
copySize = mInfo.mIL_Version.length() + 1u;
......@@ -239,6 +232,46 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
copySize =
mInfo.mILsWithVersion.size() * sizeof(decltype(mInfo.mILsWithVersion)::value_type);
break;
case DeviceInfo::Image2D_MaxWidth:
copyValue = &mInfo.mImage2D_MaxWidth;
copySize = sizeof(mInfo.mImage2D_MaxWidth);
break;
case DeviceInfo::Image2D_MaxHeight:
copyValue = &mInfo.mImage2D_MaxHeight;
copySize = sizeof(mInfo.mImage2D_MaxHeight);
break;
case DeviceInfo::Image3D_MaxWidth:
copyValue = &mInfo.mImage3D_MaxWidth;
copySize = sizeof(mInfo.mImage3D_MaxWidth);
break;
case DeviceInfo::Image3D_MaxHeight:
copyValue = &mInfo.mImage3D_MaxHeight;
copySize = sizeof(mInfo.mImage3D_MaxHeight);
break;
case DeviceInfo::Image3D_MaxDepth:
copyValue = &mInfo.mImage3D_MaxDepth;
copySize = sizeof(mInfo.mImage3D_MaxDepth);
break;
case DeviceInfo::ImageMaxBufferSize:
copyValue = &mInfo.mImageMaxBufferSize;
copySize = sizeof(mInfo.mImageMaxBufferSize);
break;
case DeviceInfo::ImageMaxArraySize:
copyValue = &mInfo.mImageMaxArraySize;
copySize = sizeof(mInfo.mImageMaxArraySize);
break;
case DeviceInfo::ImagePitchAlignment:
copyValue = &mInfo.mImagePitchAlignment;
copySize = sizeof(mInfo.mImagePitchAlignment);
break;
case DeviceInfo::ImageBaseAddressAlignment:
copyValue = &mInfo.mImageBaseAddressAlignment;
copySize = sizeof(mInfo.mImageBaseAddressAlignment);
break;
case DeviceInfo::QueueOnDeviceMaxSize:
copyValue = &mInfo.mQueueOnDeviceMaxSize;
copySize = sizeof(mInfo.mQueueOnDeviceMaxSize);
break;
case DeviceInfo::BuiltInKernels:
copyValue = mInfo.mBuiltInKernels.c_str();
copySize = mInfo.mBuiltInKernels.length() + 1u;
......@@ -303,7 +336,7 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
break;
default:
WARN() << "CL device info " << name << " is not (yet) supported";
ASSERT(false);
return CL_INVALID_VALUE;
}
......@@ -313,6 +346,8 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
}
if (value != nullptr)
{
// CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return
// type as specified in the Device Queries table and param_value is not a NULL value
if (valueSize < copySize)
{
return CL_INVALID_VALUE;
......@@ -354,7 +389,7 @@ cl_int Device::createSubDevices(const cl_device_partition_property *properties,
DevicePtr Device::CreateDevice(Platform &platform,
Device *parent,
cl_device_type type,
DeviceType type,
const CreateImplFunc &createImplFunc)
{
DevicePtr device(new Device(platform, parent, type, createImplFunc));
......@@ -371,7 +406,7 @@ bool Device::IsValid(const _cl_device_id *device)
Device::Device(Platform &platform,
Device *parent,
cl_device_type type,
DeviceType type,
const CreateImplFunc &createImplFunc)
: _cl_device_id(platform.getDispatch()),
mPlatform(platform),
......
......@@ -52,16 +52,17 @@ class Device final : public _cl_device_id, public Object
static DevicePtr CreateDevice(Platform &platform,
Device *parent,
cl_device_type type,
DeviceType type,
const CreateImplFunc &createImplFunc);
static bool IsValid(const _cl_device_id *device);
static bool IsValidType(cl_device_type type);
static bool IsValidAndVersionOrNewer(const _cl_device_id *device, cl_uint major, cl_uint minor);
static bool IsValidType(DeviceType type);
private:
Device(Platform &platform,
Device *parent,
cl_device_type type,
DeviceType type,
const CreateImplFunc &createImplFunc);
void destroySubDevice(Device *device);
......@@ -134,9 +135,16 @@ inline cl_int Device::getInfoULong(DeviceInfo name, cl_ulong *value) const
return mImpl->getInfoULong(name, value);
}
inline bool Device::IsValidType(cl_device_type type)
inline bool Device::IsValidAndVersionOrNewer(const _cl_device_id *device,
cl_uint major,
cl_uint minor)
{
return type <= CL_DEVICE_TYPE_CUSTOM || type == CL_DEVICE_TYPE_ALL;
return IsValid(device) && static_cast<const Device *>(device)->isVersionOrNewer(major, minor);
}
inline bool Device::IsValidType(DeviceType type)
{
return type.get() <= CL_DEVICE_TYPE_CUSTOM || type == CL_DEVICE_TYPE_ALL;
}
} // namespace cl
......
......@@ -77,6 +77,8 @@ cl_int Image::getInfo(ImageInfo name, size_t valueSize, void *value, size_t *val
if (value != nullptr)
{
// CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
// as described in the Image Object Queries table and param_value is not NULL.
if (valueSize < copySize)
{
return CL_INVALID_VALUE;
......@@ -116,12 +118,12 @@ bool Image::IsValid(const _cl_mem *image)
Image::Image(Context &context,
PropArray &&properties,
cl_mem_flags flags,
MemFlags flags,
const cl_image_format &format,
const ImageDescriptor &desc,
Memory *parent,
void *hostPtr,
cl_int *errcodeRet)
cl_int &errorCode)
: Memory(*this,
context,
std::move(properties),
......@@ -130,7 +132,7 @@ Image::Image(Context &context,
desc,
parent,
hostPtr,
errcodeRet),
errorCode),
mFormat(format),
mDesc(desc)
{}
......
......@@ -30,12 +30,12 @@ class Image final : public Memory
private:
Image(Context &context,
PropArray &&properties,
cl_mem_flags flags,
MemFlags flags,
const cl_image_format &format,
const ImageDescriptor &desc,
Memory *parent,
void *hostPtr,
cl_int *errcodeRet);
cl_int &errorCode);
const cl_image_format mFormat;
const ImageDescriptor mDesc;
......
......@@ -95,6 +95,8 @@ cl_int Memory::getInfo(MemInfo name, size_t valueSize, void *value, size_t *valu
if (value != nullptr)
{
// CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
// as described in the Memory Object Info table and param_value is not NULL.
if (valueSize < copySize)
{
return CL_INVALID_VALUE;
......@@ -122,25 +124,25 @@ bool Memory::IsValid(const _cl_mem *memory)
Memory::Memory(const Buffer &buffer,
Context &context,
PropArray &&properties,
cl_mem_flags flags,
MemFlags flags,
size_t size,
void *hostPtr,
cl_int *errcodeRet)
cl_int &errorCode)
: _cl_mem(context.getDispatch()),
mContext(&context),
mProperties(std::move(properties)),
mFlags(flags),
mHostPtr((flags & CL_MEM_USE_HOST_PTR) != 0u ? hostPtr : nullptr),
mImpl(context.mImpl->createBuffer(buffer, size, hostPtr, errcodeRet)),
mHostPtr(flags.isSet(CL_MEM_USE_HOST_PTR) ? hostPtr : nullptr),
mImpl(context.mImpl->createBuffer(buffer, size, hostPtr, errorCode)),
mSize(size)
{}
Memory::Memory(const Buffer &buffer,
Buffer &parent,
cl_mem_flags flags,
MemFlags flags,
size_t offset,
size_t size,
cl_int *errcodeRet)
cl_int &errorCode)
: _cl_mem(parent.getDispatch()),
mContext(parent.mContext),
mFlags(flags),
......@@ -148,27 +150,27 @@ Memory::Memory(const Buffer &buffer,
: nullptr),
mParent(&parent),
mOffset(offset),
mImpl(parent.mImpl->createSubBuffer(buffer, size, errcodeRet)),
mImpl(parent.mImpl->createSubBuffer(buffer, size, errorCode)),
mSize(size)
{}
Memory::Memory(const Image &image,
Context &context,
PropArray &&properties,
cl_mem_flags flags,
MemFlags flags,
const cl_image_format &format,
const ImageDescriptor &desc,
Memory *parent,
void *hostPtr,
cl_int *errcodeRet)
cl_int &errorCode)
: _cl_mem(context.getDispatch()),
mContext(&context),
mProperties(std::move(properties)),
mFlags(flags),
mHostPtr((flags & CL_MEM_USE_HOST_PTR) != 0u ? hostPtr : nullptr),
mHostPtr(flags.isSet(CL_MEM_USE_HOST_PTR) ? hostPtr : nullptr),
mParent(parent),
mImpl(context.mImpl->createImage(image, format, desc, hostPtr, errcodeRet)),
mSize(mImpl ? mImpl->getSize() : 0u)
mImpl(context.mImpl->createImage(image, format, desc, hostPtr, errorCode)),
mSize(mImpl ? mImpl->getSize(errorCode) : 0u)
{}
} // namespace cl
......@@ -27,7 +27,7 @@ class Memory : public _cl_mem, public Object
const Context &getContext() const;
const PropArray &getProperties() const;
cl_mem_flags getFlags() const;
MemFlags getFlags() const;
void *getHostPtr() const;
const MemoryRefPtr &getParent() const;
size_t getOffset() const;
......@@ -43,31 +43,31 @@ class Memory : public _cl_mem, public Object
Memory(const Buffer &buffer,
Context &context,
PropArray &&properties,
cl_mem_flags flags,
MemFlags flags,
size_t size,
void *hostPtr,
cl_int *errcodeRet);
cl_int &errorCode);
Memory(const Buffer &buffer,
Buffer &parent,
cl_mem_flags flags,
MemFlags flags,
size_t offset,
size_t size,
cl_int *errcodeRet);
cl_int &errorCode);
Memory(const Image &image,
Context &context,
PropArray &&properties,
cl_mem_flags flags,
MemFlags flags,
const cl_image_format &format,
const ImageDescriptor &desc,
Memory *parent,
void *hostPtr,
cl_int *errcodeRet);
cl_int &errorCode);
const ContextRefPtr mContext;
const PropArray mProperties;
const cl_mem_flags mFlags;
const MemFlags mFlags;
void *const mHostPtr = nullptr;
const MemoryRefPtr mParent;
const size_t mOffset = 0u;
......@@ -90,7 +90,7 @@ inline const Memory::PropArray &Memory::getProperties() const
return mProperties;
}
inline cl_mem_flags Memory::getFlags() const
inline MemFlags Memory::getFlags() const
{
return mFlags;
}
......
......@@ -16,13 +16,12 @@ namespace cl
namespace
{
bool IsDeviceTypeMatch(cl_device_type select, cl_device_type type)
bool IsDeviceTypeMatch(DeviceType select, DeviceType type)
{
// The type 'cl_device_type' is a bitfield, so masking out the selected bits indicates
// if a given type is a match. A custom device is an exception, which only matches
// if it was explicitely selected, as defined here:
// The type 'DeviceType' is a bitfield, so it matches if any selected bit is set.
// A custom device is an exception, which only matches if it was explicitely selected, see:
// https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#clGetDeviceIDs
return type == CL_DEVICE_TYPE_CUSTOM ? select == CL_DEVICE_TYPE_CUSTOM : (type & select) != 0u;
return type == CL_DEVICE_TYPE_CUSTOM ? select == CL_DEVICE_TYPE_CUSTOM : type.isSet(select);
}
Context::PropArray ParseContextProperties(const cl_context_properties *properties,
......@@ -112,11 +111,14 @@ cl_int Platform::getInfo(PlatformInfo name,
copySize = sizeof(kIcdSuffix);
break;
default:
ASSERT(false);
return CL_INVALID_VALUE;
}
if (value != nullptr)
{
// CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
// as specified in the OpenCL Platform Queries table, and param_value is not a NULL value.
if (valueSize < copySize)
{
return CL_INVALID_VALUE;
......@@ -133,7 +135,7 @@ cl_int Platform::getInfo(PlatformInfo name,
return CL_SUCCESS;
}
cl_int Platform::getDeviceIDs(cl_device_type deviceType,
cl_int Platform::getDeviceIDs(DeviceType deviceType,
cl_uint numEntries,
cl_device_id *devices,
cl_uint *numDevices) const
......@@ -154,7 +156,14 @@ cl_int Platform::getDeviceIDs(cl_device_type deviceType,
{
*numDevices = found;
}
return found == 0u ? CL_DEVICE_NOT_FOUND : CL_SUCCESS;
// CL_DEVICE_NOT_FOUND if no OpenCL devices that matched device_type were found.
if (found == 0u)
{
return CL_DEVICE_NOT_FOUND;
}
return CL_SUCCESS;
}
void Platform::CreatePlatform(const cl_icd_dispatch &dispatch, const CreateImplFunc &createImplFunc)
......@@ -166,20 +175,20 @@ void Platform::CreatePlatform(const cl_icd_dispatch &dispatch, const CreateImplF
}
}
cl_int Platform::GetPlatformIDs(cl_uint num_entries,
cl_int Platform::GetPlatformIDs(cl_uint numEntries,
cl_platform_id *platforms,
cl_uint *num_platforms)
cl_uint *numPlatforms)
{
const PtrList &platformList = GetList();
if (num_platforms != nullptr)
const PtrList &platformList = GetPlatforms();
if (numPlatforms != nullptr)
{
*num_platforms = static_cast<cl_uint>(platformList.size());
*numPlatforms = static_cast<cl_uint>(platformList.size());
}
if (platforms != nullptr)
{
cl_uint entry = 0u;
auto platformIt = platformList.cbegin();
while (entry < num_entries && platformIt != platformList.cend())
while (entry < numEntries && platformIt != platformList.cend())
{
platforms[entry++] = (*platformIt++).get();
}
......@@ -192,7 +201,7 @@ cl_context Platform::CreateContext(const cl_context_properties *properties,
const cl_device_id *devices,
ContextErrorCB notify,
void *userData,
cl_int *errcodeRet)
cl_int &errorCode)
{
Platform *platform = nullptr;
bool userSync = false;
......@@ -203,25 +212,23 @@ cl_context Platform::CreateContext(const cl_context_properties *properties,
{
refDevices.emplace_back(static_cast<Device *>(*devices++));
}
return platform->createContext(
new Context(*platform, std::move(propArray), std::move(refDevices), notify, userData,
userSync, errcodeRet),
errcodeRet);
return platform->createContext(new Context(*platform, std::move(propArray),
std::move(refDevices), notify, userData, userSync,
errorCode));
}
cl_context Platform::CreateContextFromType(const cl_context_properties *properties,
cl_device_type deviceType,
DeviceType deviceType,
ContextErrorCB notify,
void *userData,
cl_int *errcodeRet)
cl_int &errorCode)
{
Platform *platform = nullptr;
bool userSync = false;
Context::PropArray propArray = ParseContextProperties(properties, platform, userSync);
ASSERT(platform != nullptr);
return platform->createContext(new Context(*platform, std::move(propArray), deviceType, notify,
userData, userSync, errcodeRet),
errcodeRet);
userData, userSync, errorCode));
}
Platform::Platform(const cl_icd_dispatch &dispatch, const CreateImplFunc &createImplFunc)
......@@ -231,18 +238,14 @@ Platform::Platform(const cl_icd_dispatch &dispatch, const CreateImplFunc &create
mDevices(mImpl->createDevices(*this))
{}
cl_context Platform::createContext(Context *context, cl_int *errcodeRet)
cl_context Platform::createContext(Context *context)
{
mContexts.emplace_back(context);
if (!mContexts.back()->mImpl)
if (!mContexts.back()->mImpl || mContexts.back()->mDevices.empty())
{
mContexts.back()->release();
return nullptr;
}
if (errcodeRet != nullptr)
{
*errcodeRet = CL_SUCCESS;
}
return mContexts.back().get();
}
......
......@@ -15,8 +15,6 @@
#include "anglebase/no_destructor.h"
#include <functional>
namespace cl
{
......@@ -41,7 +39,7 @@ class Platform final : public _cl_platform_id, public Object
cl_int getInfo(PlatformInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const;
cl_int getDeviceIDs(cl_device_type deviceType,
cl_int getDeviceIDs(DeviceType deviceType,
cl_uint numEntries,
cl_device_id *devices,
cl_uint *numDevices) const;
......@@ -49,22 +47,22 @@ class Platform final : public _cl_platform_id, public Object
static void CreatePlatform(const cl_icd_dispatch &dispatch,
const CreateImplFunc &createImplFunc);
static cl_int GetPlatformIDs(cl_uint num_entries,
static cl_int GetPlatformIDs(cl_uint numEntries,
cl_platform_id *platforms,
cl_uint *num_platforms);
cl_uint *numPlatforms);
static cl_context CreateContext(const cl_context_properties *properties,
cl_uint numDevices,
const cl_device_id *devices,
ContextErrorCB notify,
void *userData,
cl_int *errcodeRet);
cl_int &errorCode);
static cl_context CreateContextFromType(const cl_context_properties *properties,
cl_device_type deviceType,
DeviceType deviceType,
ContextErrorCB notify,
void *userData,
cl_int *errcodeRet);
cl_int &errorCode);
static const PtrList &GetPlatforms();
static Platform *GetDefault();
......@@ -77,7 +75,7 @@ class Platform final : public _cl_platform_id, public Object
private:
Platform(const cl_icd_dispatch &dispatch, const CreateImplFunc &createImplFunc);
cl_context createContext(Context *context, cl_int *errcodeRet);
cl_context createContext(Context *context);
void destroyContext(Context *context);
static PtrList &GetList();
......
......@@ -98,6 +98,8 @@ cl_int Program::getInfo(ProgramInfo name, size_t valueSize, void *value, size_t
if (value != nullptr)
{
// CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
// as described in the Program Object Queries table and param_value is not NULL.
if (valueSize < copySize)
{
return CL_INVALID_VALUE;
......@@ -122,45 +124,45 @@ bool Program::IsValid(const _cl_program *program)
}) != platforms.cend();
}
Program::Program(Context &context, std::string &&source, cl_int *errcodeRet)
Program::Program(Context &context, std::string &&source, cl_int &errorCode)
: _cl_program(context.getDispatch()),
mContext(&context),
mDevices(context.getDevices()),
mImpl(context.mImpl->createProgramWithSource(*this, source, errcodeRet)),
mImpl(context.mImpl->createProgramWithSource(*this, source, errorCode)),
mSource(std::move(source))
{}
Program::Program(Context &context, const void *il, size_t length, cl_int *errcodeRet)
Program::Program(Context &context, const void *il, size_t length, cl_int &errorCode)
: _cl_program(context.getDispatch()),
mContext(&context),
mDevices(context.getDevices()),
mIL(static_cast<const char *>(il), length),
mImpl(context.mImpl->createProgramWithIL(*this, il, length, errcodeRet)),
mSource(mImpl ? mImpl->getSource() : std::string{})
mImpl(context.mImpl->createProgramWithIL(*this, il, length, errorCode)),
mSource(mImpl ? mImpl->getSource(errorCode) : std::string{})
{}
Program::Program(Context &context,
DeviceRefList &&devices,
Binaries &&binaries,
cl_int *binaryStatus,
cl_int *errcodeRet)
cl_int &errorCode)
: _cl_program(context.getDispatch()),
mContext(&context),
mDevices(std::move(devices)),
mImpl(context.mImpl->createProgramWithBinary(*this, binaries, binaryStatus, errcodeRet)),
mSource(mImpl ? mImpl->getSource() : std::string{}),
mImpl(context.mImpl->createProgramWithBinary(*this, binaries, binaryStatus, errorCode)),
mSource(mImpl ? mImpl->getSource(errorCode) : std::string{}),
mBinaries(std::move(binaries))
{}
Program::Program(Context &context,
DeviceRefList &&devices,
const char *kernelNames,
cl_int *errcodeRet)
cl_int &errorCode)
: _cl_program(context.getDispatch()),
mContext(&context),
mDevices(std::move(devices)),
mImpl(context.mImpl->createProgramWithBuiltInKernels(*this, kernelNames, errcodeRet)),
mSource(mImpl ? mImpl->getSource() : std::string{})
mImpl(context.mImpl->createProgramWithBuiltInKernels(*this, kernelNames, errorCode)),
mSource(mImpl ? mImpl->getSource(errorCode) : std::string{})
{}
} // namespace cl
......@@ -32,16 +32,16 @@ class Program final : public _cl_program, public Object
static bool IsValid(const _cl_program *program);
private:
Program(Context &context, std::string &&source, cl_int *errcodeRet);
Program(Context &context, const void *il, size_t length, cl_int *errcodeRet);
Program(Context &context, std::string &&source, cl_int &errorCode);
Program(Context &context, const void *il, size_t length, cl_int &errorCode);
Program(Context &context,
DeviceRefList &&devices,
Binaries &&binaries,
cl_int *binaryStatus,
cl_int *errcodeRet);
cl_int &errorCode);
Program(Context &context, DeviceRefList &&devices, const char *kernelNames, cl_int *errcodeRet);
Program(Context &context, DeviceRefList &&devices, const char *kernelNames, cl_int &errorCode);
const ContextRefPtr mContext;
const DeviceRefList mDevices;
......
......@@ -72,6 +72,7 @@ class RefPointer
T *operator->() const { return mCLObject; }
T &operator*() const { return *mCLObject; }
bool isValid() const { return mCLObject != nullptr; }
T *get() const { return mCLObject; }
explicit operator bool() const { return mCLObject != nullptr; }
......
......@@ -73,6 +73,8 @@ cl_int Sampler::getInfo(SamplerInfo name, size_t valueSize, void *value, size_t
if (value != nullptr)
{
// CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
// as described in the Sampler Object Queries table and param_value is not NULL.
if (valueSize < copySize)
{
return CL_INVALID_VALUE;
......@@ -102,14 +104,14 @@ Sampler::Sampler(Context &context,
cl_bool normalizedCoords,
AddressingMode addressingMode,
FilterMode filterMode,
cl_int *errcodeRet)
cl_int &errorCode)
: _cl_sampler(context.getDispatch()),
mContext(&context),
mProperties(std::move(properties)),
mNormalizedCoords(normalizedCoords),
mAddressingMode(addressingMode),
mFilterMode(filterMode),
mImpl(context.mImpl->createSampler(*this, errcodeRet))
mImpl(context.mImpl->createSampler(*this, errorCode))
{}
} // namespace cl
......@@ -41,7 +41,7 @@ class Sampler final : public _cl_sampler, public Object
cl_bool normalizedCoords,
AddressingMode addressingMode,
FilterMode filterMode,
cl_int *errcodeRet);
cl_int &errorCode);
const ContextRefPtr mContext;
const PropArray mProperties;
......
......@@ -8,12 +8,14 @@
#ifndef LIBANGLE_CLTYPES_H_
#define LIBANGLE_CLTYPES_H_
#include "libANGLE/CLBitField.h"
#include "libANGLE/CLRefPointer.h"
#include "common/PackedCLEnums_autogen.h"
// Include frequently used standard headers
#include <algorithm>
#include <functional>
#include <list>
#include <memory>
#include <string>
......
......@@ -21,7 +21,7 @@ class CLCommandQueueImpl : angle::NonCopyable
CLCommandQueueImpl(const cl::CommandQueue &commandQueue);
virtual ~CLCommandQueueImpl();
virtual cl_int setProperty(cl_command_queue_properties properties, cl_bool enable) = 0;
virtual cl_int setProperty(cl::CommandQueueProperties properties, cl_bool enable) = 0;
protected:
const cl::CommandQueue &mCommandQueue;
......
......@@ -25,41 +25,41 @@ class CLContextImpl : angle::NonCopyable
CLContextImpl(const cl::Context &context);
virtual ~CLContextImpl();
virtual cl::DeviceRefList getDevices() const = 0;
virtual cl::DeviceRefList getDevices(cl_int &errorCode) const = 0;
virtual CLCommandQueueImpl::Ptr createCommandQueue(const cl::CommandQueue &commandQueue,
cl_int *errcodeRet) = 0;
cl_int &errorCode) = 0;
virtual CLMemoryImpl::Ptr createBuffer(const cl::Buffer &buffer,
size_t size,
void *hostPtr,
cl_int *errcodeRet) = 0;
cl_int &errorCode) = 0;
virtual CLMemoryImpl::Ptr createImage(const cl::Image &image,
const cl_image_format &format,
const cl::ImageDescriptor &desc,
void *hostPtr,
cl_int *errcodeRet) = 0;
cl_int &errorCode) = 0;
virtual CLSamplerImpl::Ptr createSampler(const cl::Sampler &sampler, cl_int *errcodeRet) = 0;
virtual CLSamplerImpl::Ptr createSampler(const cl::Sampler &sampler, cl_int &errorCode) = 0;
virtual CLProgramImpl::Ptr createProgramWithSource(const cl::Program &program,
const std::string &source,
cl_int *errcodeRet) = 0;
cl_int &errorCode) = 0;
virtual CLProgramImpl::Ptr createProgramWithIL(const cl::Program &program,
const void *il,
size_t length,
cl_int *errcodeRet) = 0;
cl_int &errorCode) = 0;
virtual CLProgramImpl::Ptr createProgramWithBinary(const cl::Program &program,
const cl::Binaries &binaries,
cl_int *binaryStatus,
cl_int *errcodeRet) = 0;
cl_int &errorCode) = 0;
virtual CLProgramImpl::Ptr createProgramWithBuiltInKernels(const cl::Program &program,
const char *kernel_names,
cl_int *errcodeRet) = 0;
cl_int &errorCode) = 0;
protected:
const cl::Context &mContext;
......
......@@ -14,7 +14,7 @@ namespace rx
CLDeviceImpl::Info::Info() = default;
CLDeviceImpl::Info::Info(cl_device_type type) : mType(type) {}
CLDeviceImpl::Info::Info(cl::DeviceType type) : mType(type) {}
CLDeviceImpl::Info::~Info() = default;
......
......@@ -21,7 +21,7 @@ class CLDeviceImpl : angle::NonCopyable
struct Info
{
Info();
explicit Info(cl_device_type type);
explicit Info(cl::DeviceType type);
~Info();
Info(const Info &) = delete;
......@@ -30,10 +30,10 @@ class CLDeviceImpl : angle::NonCopyable
Info(Info &&);
Info &operator=(Info &&);
bool isValid() const { return mType != 0u; }
bool isValid() const { return mVersion != 0u; }
// In the order as they appear in the OpenCL specification V3.0.7, table 5
cl_device_type mType = 0u;
cl::DeviceType mType;
std::vector<size_t> mMaxWorkItemSizes;
cl_ulong mMaxMemAllocSize = 0u;
cl_bool mImageSupport = CL_FALSE;
......@@ -48,6 +48,7 @@ class CLDeviceImpl : angle::NonCopyable
size_t mImageMaxArraySize = 0u;
cl_uint mImagePitchAlignment = 0u;
cl_uint mImageBaseAddressAlignment = 0u;
cl_uint mQueueOnDeviceMaxSize = 0u;
std::string mBuiltInKernels;
NameVersionVector mBuiltInKernelsWithVersion;
std::string mVersionStr;
......@@ -63,7 +64,7 @@ class CLDeviceImpl : angle::NonCopyable
CLDeviceImpl(const cl::Device &device);
virtual ~CLDeviceImpl();
virtual Info createInfo(cl_device_type type) const = 0;
virtual Info createInfo(cl::DeviceType type) const = 0;
virtual cl_int getInfoUInt(cl::DeviceInfo name, cl_uint *value) const = 0;
virtual cl_int getInfoULong(cl::DeviceInfo name, cl_ulong *value) const = 0;
......
......@@ -21,11 +21,11 @@ class CLMemoryImpl : angle::NonCopyable
CLMemoryImpl(const cl::Memory &memory);
virtual ~CLMemoryImpl();
virtual size_t getSize() const = 0;
virtual size_t getSize(cl_int &errorCode) const = 0;
virtual CLMemoryImpl::Ptr createSubBuffer(const cl::Buffer &buffer,
size_t size,
cl_int *errcodeRet) = 0;
cl_int &errorCode) = 0;
protected:
const cl::Memory &mMemory;
......
......@@ -50,19 +50,15 @@ class CLPlatformImpl : angle::NonCopyable
virtual Info createInfo() const = 0;
virtual cl::DevicePtrList createDevices(cl::Platform &platform) const = 0;
virtual CLContextImpl::Ptr createContext(const cl::Context &context,
virtual CLContextImpl::Ptr createContext(cl::Context &context,
const cl::DeviceRefList &devices,
cl::ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet) = 0;
cl_int &errorCode) = 0;
virtual CLContextImpl::Ptr createContextFromType(const cl::Context &context,
cl_device_type deviceType,
cl::ContextErrorCB notify,
void *userData,
virtual CLContextImpl::Ptr createContextFromType(cl::Context &context,
cl::DeviceType deviceType,
bool userSync,
cl_int *errcodeRet) = 0;
cl_int &errorCode) = 0;
protected:
const cl::Platform &mPlatform;
......
......@@ -21,7 +21,7 @@ class CLProgramImpl : angle::NonCopyable
CLProgramImpl(const cl::Program &program);
virtual ~CLProgramImpl();
virtual std::string getSource() const = 0;
virtual std::string getSource(cl_int &errorCode) const = 0;
protected:
const cl::Program &mProgram;
......
......@@ -24,9 +24,10 @@ CLCommandQueueCL::~CLCommandQueueCL()
}
}
cl_int CLCommandQueueCL::setProperty(cl_command_queue_properties properties, cl_bool enable)
cl_int CLCommandQueueCL::setProperty(cl::CommandQueueProperties properties, cl_bool enable)
{
return mNative->getDispatch().clSetCommandQueueProperty(mNative, properties, enable, nullptr);
return mNative->getDispatch().clSetCommandQueueProperty(mNative, properties.get(), enable,
nullptr);
}
} // namespace rx
......@@ -22,7 +22,7 @@ class CLCommandQueueCL : public CLCommandQueueImpl
CLCommandQueueCL(const cl::CommandQueue &commandQueue, cl_command_queue native);
~CLCommandQueueCL() override;
cl_int setProperty(cl_command_queue_properties properties, cl_bool enable) override;
cl_int setProperty(cl::CommandQueueProperties properties, cl_bool enable) override;
private:
const cl_command_queue mNative;
......
......@@ -21,41 +21,41 @@ class CLContextCL : public CLContextImpl
CLContextCL(const cl::Context &context, cl_context native);
~CLContextCL() override;
cl::DeviceRefList getDevices() const override;
cl::DeviceRefList getDevices(cl_int &errorCode) const override;
CLCommandQueueImpl::Ptr createCommandQueue(const cl::CommandQueue &commandQueue,
cl_int *errcodeRet) override;
cl_int &errorCode) override;
CLMemoryImpl::Ptr createBuffer(const cl::Buffer &buffer,
size_t size,
void *hostPtr,
cl_int *errcodeRet) override;
cl_int &errorCode) override;
CLMemoryImpl::Ptr createImage(const cl::Image &image,
const cl_image_format &format,
const cl::ImageDescriptor &desc,
void *hostPtr,
cl_int *errcodeRet) override;
cl_int &errorCode) override;
CLSamplerImpl::Ptr createSampler(const cl::Sampler &sampler, cl_int *errcodeRet) override;
CLSamplerImpl::Ptr createSampler(const cl::Sampler &sampler, cl_int &errorCode) override;
CLProgramImpl::Ptr createProgramWithSource(const cl::Program &program,
const std::string &source,
cl_int *errcodeRet) override;
cl_int &errorCode) override;
CLProgramImpl::Ptr createProgramWithIL(const cl::Program &program,
const void *il,
size_t length,
cl_int *errcodeRet) override;
cl_int &errorCode) override;
CLProgramImpl::Ptr createProgramWithBinary(const cl::Program &program,
const cl::Binaries &binaries,
cl_int *binaryStatus,
cl_int *errcodeRet) override;
cl_int &errorCode) override;
CLProgramImpl::Ptr createProgramWithBuiltInKernels(const cl::Program &program,
const char *kernel_names,
cl_int *errcodeRet) override;
cl_int &errorCode) override;
private:
const cl_context mNative;
......
......@@ -65,7 +65,7 @@ CLDeviceCL::~CLDeviceCL()
}
}
CLDeviceImpl::Info CLDeviceCL::createInfo(cl_device_type type) const
CLDeviceImpl::Info CLDeviceCL::createInfo(cl::DeviceType type) const
{
Info info(type);
std::vector<char> valString;
......@@ -134,7 +134,8 @@ CLDeviceImpl::Info CLDeviceCL::createInfo(cl_device_type type) const
if (info.mVersion >= CL_MAKE_VERSION(2, 0, 0) &&
(!GetDeviceInfo(mNative, cl::DeviceInfo::ImagePitchAlignment, info.mImagePitchAlignment) ||
!GetDeviceInfo(mNative, cl::DeviceInfo::ImageBaseAddressAlignment,
info.mImageBaseAddressAlignment)))
info.mImageBaseAddressAlignment) ||
!GetDeviceInfo(mNative, cl::DeviceInfo::QueueOnDeviceMaxSize, info.mQueueOnDeviceMaxSize)))
{
return Info{};
}
......@@ -211,14 +212,15 @@ cl_int CLDeviceCL::createSubDevices(cl::Device &device,
mNative, properties, numDevices, nativeSubDevices.data(), nullptr);
if (result == CL_SUCCESS)
{
cl::DeviceType type = device.getInfo().mType;
type.clear(CL_DEVICE_TYPE_DEFAULT);
for (cl_device_id nativeSubDevice : nativeSubDevices)
{
const cl::Device::CreateImplFunc createImplFunc = [&](const cl::Device &device) {
return Ptr(new CLDeviceCL(device, nativeSubDevice));
};
subDeviceList.emplace_back(cl::Device::CreateDevice(
device.getPlatform(), &device, device.getInfo().mType & ~CL_DEVICE_TYPE_DEFAULT,
createImplFunc));
subDeviceList.emplace_back(
cl::Device::CreateDevice(device.getPlatform(), &device, type, createImplFunc));
if (!subDeviceList.back())
{
subDeviceList.clear();
......
......@@ -22,7 +22,7 @@ class CLDeviceCL : public CLDeviceImpl
cl_device_id getNative();
Info createInfo(cl_device_type type) const override;
Info createInfo(cl::DeviceType type) const override;
cl_int getInfoUInt(cl::DeviceInfo name, cl_uint *value) const override;
cl_int getInfoULong(cl::DeviceInfo name, cl_ulong *value) const override;
......
......@@ -25,13 +25,13 @@ CLMemoryCL::~CLMemoryCL()
}
}
size_t CLMemoryCL::getSize() const
size_t CLMemoryCL::getSize(cl_int &errorCode) const
{
size_t size = 0u;
if (mNative->getDispatch().clGetMemObjectInfo(mNative, CL_MEM_SIZE, sizeof(size), &size,
nullptr) != CL_SUCCESS)
errorCode = mNative->getDispatch().clGetMemObjectInfo(mNative, CL_MEM_SIZE, sizeof(size), &size,
nullptr);
if (errorCode != CL_SUCCESS)
{
ERR() << "Failed to query CL memory object size";
return 0u;
}
return size;
......@@ -39,11 +39,11 @@ size_t CLMemoryCL::getSize() const
CLMemoryImpl::Ptr CLMemoryCL::createSubBuffer(const cl::Buffer &buffer,
size_t size,
cl_int *errcodeRet)
cl_int &errorCode)
{
const cl_buffer_region region = {buffer.getOffset(), size};
const cl_mem nativeBuffer = mNative->getDispatch().clCreateSubBuffer(
mNative, buffer.getFlags(), CL_BUFFER_CREATE_TYPE_REGION, &region, errcodeRet);
mNative, buffer.getFlags().get(), CL_BUFFER_CREATE_TYPE_REGION, &region, &errorCode);
return CLMemoryImpl::Ptr(nativeBuffer != nullptr ? new CLMemoryCL(buffer, nativeBuffer)
: nullptr);
}
......
......@@ -21,11 +21,11 @@ class CLMemoryCL : public CLMemoryImpl
CLMemoryCL(const cl::Memory &memory, cl_mem native);
~CLMemoryCL() override;
size_t getSize() const override;
size_t getSize(cl_int &errorCode) const override;
CLMemoryImpl::Ptr createSubBuffer(const cl::Buffer &buffer,
size_t size,
cl_int *errcodeRet) override;
cl_int &errorCode) override;
private:
const cl_mem mNative;
......
......@@ -315,7 +315,7 @@ cl::DevicePtrList CLPlatformCL::createDevices(cl::Platform &platform) const
{
// Fetch all device types for front end initialization, and find the default device.
// If none exists declare first device as default.
std::vector<cl_device_type> types(nativeDevices.size(), 0u);
std::vector<cl::DeviceType> types(nativeDevices.size());
size_t defaultIndex = 0u;
for (size_t index = 0u; index < nativeDevices.size(); ++index)
{
......@@ -324,7 +324,7 @@ cl::DevicePtrList CLPlatformCL::createDevices(cl::Platform &platform) const
nullptr) == CL_SUCCESS)
{
// If default device found, select it
if ((types[index] & CL_DEVICE_TYPE_DEFAULT) != 0u)
if (types[index].isSet(CL_DEVICE_TYPE_DEFAULT))
{
defaultIndex = index;
}
......@@ -341,11 +341,11 @@ cl::DevicePtrList CLPlatformCL::createDevices(cl::Platform &platform) const
// Make sure the default bit is set in exactly one device
if (index == defaultIndex)
{
types[index] |= CL_DEVICE_TYPE_DEFAULT;
types[index].set(CL_DEVICE_TYPE_DEFAULT);
}
else
{
types[index] &= ~CL_DEVICE_TYPE_DEFAULT;
types[index].clear(CL_DEVICE_TYPE_DEFAULT);
}
const cl::Device::CreateImplFunc createImplFunc = [&](const cl::Device &device) {
......@@ -369,12 +369,10 @@ cl::DevicePtrList CLPlatformCL::createDevices(cl::Platform &platform) const
return devices;
}
CLContextImpl::Ptr CLPlatformCL::createContext(const cl::Context &context,
CLContextImpl::Ptr CLPlatformCL::createContext(cl::Context &context,
const cl::DeviceRefList &devices,
cl::ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet)
cl_int &errorCode)
{
cl_context_properties properties[] = {
CL_CONTEXT_PLATFORM, reinterpret_cast<cl_context_properties>(mNative),
......@@ -389,25 +387,23 @@ CLContextImpl::Ptr CLPlatformCL::createContext(const cl::Context &context,
CLContextImpl::Ptr contextImpl;
cl_context nativeContext = mNative->getDispatch().clCreateContext(
properties, static_cast<cl_uint>(nativeDevices.size()), nativeDevices.data(), notify,
userData, errcodeRet);
properties, static_cast<cl_uint>(nativeDevices.size()), nativeDevices.data(),
cl::Context::ErrorCallback, &context, &errorCode);
return CLContextImpl::Ptr(nativeContext != nullptr ? new CLContextCL(context, nativeContext)
: nullptr);
}
CLContextImpl::Ptr CLPlatformCL::createContextFromType(const cl::Context &context,
cl_device_type deviceType,
cl::ContextErrorCB notify,
void *userData,
CLContextImpl::Ptr CLPlatformCL::createContextFromType(cl::Context &context,
cl::DeviceType deviceType,
bool userSync,
cl_int *errcodeRet)
cl_int &errorCode)
{
cl_context_properties properties[] = {
CL_CONTEXT_PLATFORM, reinterpret_cast<cl_context_properties>(mNative),
userSync && mPlatform.isVersionOrNewer(1u, 2u) ? CL_CONTEXT_INTEROP_USER_SYNC : 0, CL_TRUE,
0};
cl_context nativeContext = mNative->getDispatch().clCreateContextFromType(
properties, deviceType, notify, userData, errcodeRet);
properties, deviceType.get(), cl::Context::ErrorCallback, &context, &errorCode);
return CLContextImpl::Ptr(nativeContext != nullptr ? new CLContextCL(context, nativeContext)
: nullptr);
}
......
......@@ -23,19 +23,15 @@ class CLPlatformCL : public CLPlatformImpl
Info createInfo() const override;
cl::DevicePtrList createDevices(cl::Platform &platform) const override;
CLContextImpl::Ptr createContext(const cl::Context &context,
CLContextImpl::Ptr createContext(cl::Context &context,
const cl::DeviceRefList &devices,
cl::ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet) override;
cl_int &errorCode) override;
CLContextImpl::Ptr createContextFromType(const cl::Context &context,
cl_device_type deviceType,
cl::ContextErrorCB notify,
void *userData,
CLContextImpl::Ptr createContextFromType(cl::Context &context,
cl::DeviceType deviceType,
bool userSync,
cl_int *errcodeRet) override;
cl_int &errorCode) override;
static void Initialize(const cl_icd_dispatch &dispatch, bool isIcd);
......
......@@ -24,27 +24,24 @@ CLProgramCL::~CLProgramCL()
}
}
std::string CLProgramCL::getSource() const
std::string CLProgramCL::getSource(cl_int &errorCode) const
{
size_t size = 0u;
if (mNative->getDispatch().clGetProgramInfo(mNative, CL_PROGRAM_SOURCE, 0u, nullptr, &size) ==
CL_SUCCESS)
errorCode =
mNative->getDispatch().clGetProgramInfo(mNative, CL_PROGRAM_SOURCE, 0u, nullptr, &size);
if (errorCode == CL_SUCCESS)
{
if (size != 0u)
{
std::vector<char> valString(size, '\0');
if (mNative->getDispatch().clGetProgramInfo(mNative, CL_PROGRAM_SOURCE, size,
valString.data(), nullptr) == CL_SUCCESS)
errorCode = mNative->getDispatch().clGetProgramInfo(mNative, CL_PROGRAM_SOURCE, size,
valString.data(), nullptr);
if (errorCode == CL_SUCCESS)
{
return std::string(valString.data(), valString.size() - 1u);
}
}
else
{
return std::string{};
}
}
ERR() << "Failed to query CL program source";
return std::string{};
}
......
......@@ -21,7 +21,7 @@ class CLProgramCL : public CLProgramImpl
CLProgramCL(const cl::Program &program, cl_program native);
~CLProgramCL() override;
std::string getSource() const override;
std::string getSource(cl_int &errorCode) const override;
private:
const cl_program mNative;
......
......@@ -16,7 +16,7 @@ CLDeviceVk::CLDeviceVk(const cl::Device &device) : CLDeviceImpl(device) {}
CLDeviceVk::~CLDeviceVk() = default;
CLDeviceImpl::Info CLDeviceVk::createInfo(cl_device_type type) const
CLDeviceImpl::Info CLDeviceVk::createInfo(cl::DeviceType type) const
{
Info info(type);
return info;
......
......@@ -21,7 +21,7 @@ class CLDeviceVk : public CLDeviceImpl
explicit CLDeviceVk(const cl::Device &device);
~CLDeviceVk() override;
Info createInfo(cl_device_type type) const override;
Info createInfo(cl::DeviceType type) const override;
cl_int getInfoUInt(cl::DeviceInfo name, cl_uint *value) const override;
cl_int getInfoULong(cl::DeviceInfo name, cl_ulong *value) const override;
......
......@@ -58,7 +58,7 @@ CLPlatformImpl::Info CLPlatformVk::createInfo() const
cl::DevicePtrList CLPlatformVk::createDevices(cl::Platform &platform) const
{
cl_device_type type = 0u; // TODO(jplate) Fetch device type from Vulkan
cl::DeviceType type; // TODO(jplate) Fetch device type from Vulkan
cl::DevicePtrList devices;
const cl::Device::CreateImplFunc createImplFunc = [](const cl::Device &device) {
return CLDeviceVk::Ptr(new CLDeviceVk(device));
......@@ -71,23 +71,19 @@ cl::DevicePtrList CLPlatformVk::createDevices(cl::Platform &platform) const
return devices;
}
CLContextImpl::Ptr CLPlatformVk::createContext(const cl::Context &context,
CLContextImpl::Ptr CLPlatformVk::createContext(cl::Context &context,
const cl::DeviceRefList &devices,
cl::ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet)
cl_int &errorCode)
{
CLContextImpl::Ptr contextImpl;
return contextImpl;
}
CLContextImpl::Ptr CLPlatformVk::createContextFromType(const cl::Context &context,
cl_device_type deviceType,
cl::ContextErrorCB notify,
void *userData,
CLContextImpl::Ptr CLPlatformVk::createContextFromType(cl::Context &context,
cl::DeviceType deviceType,
bool userSync,
cl_int *errcodeRet)
cl_int &errorCode)
{
CLContextImpl::Ptr contextImpl;
return contextImpl;
......
......@@ -21,19 +21,15 @@ class CLPlatformVk : public CLPlatformImpl
Info createInfo() const override;
cl::DevicePtrList createDevices(cl::Platform &platform) const override;
CLContextImpl::Ptr createContext(const cl::Context &context,
CLContextImpl::Ptr createContext(cl::Context &context,
const cl::DeviceRefList &devices,
cl::ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet) override;
cl_int &errorCode) override;
CLContextImpl::Ptr createContextFromType(const cl::Context &context,
cl_device_type deviceType,
cl::ContextErrorCB notify,
void *userData,
CLContextImpl::Ptr createContextFromType(cl::Context &context,
cl::DeviceType deviceType,
bool userSync,
cl_int *errcodeRet) override;
cl_int &errorCode) override;
static void Initialize(const cl_icd_dispatch &dispatch);
......
......@@ -21,13 +21,13 @@
#include "libANGLE/CLProgram.h"
#include "libANGLE/CLSampler.h"
#define ANGLE_CL_VALIDATE_VOID(EP, ...) \
do \
{ \
if (!Validate##EP(__VA_ARGS__)) \
{ \
return; \
} \
#define ANGLE_CL_VALIDATE_VOID(EP, ...) \
do \
{ \
if (Validate##EP(__VA_ARGS__) != CL_SUCCESS) \
{ \
return; \
} \
} while (0)
#define ANGLE_CL_VALIDATE_ERROR(EP, ...) \
......@@ -40,13 +40,28 @@
} \
} while (0)
#define ANGLE_CL_VALIDATE_POINTER(EP, ...) \
do \
{ \
if (!Validate##EP(__VA_ARGS__)) \
{ \
return nullptr; \
} \
#define ANGLE_CL_VALIDATE_ERRCODE_RET(EP, ...) \
do \
{ \
cl_int errorCode = Validate##EP(__VA_ARGS__); \
if (errorCode != CL_SUCCESS) \
{ \
if (errcode_ret != nullptr) \
{ \
*errcode_ret = errorCode; \
} \
return nullptr; \
} \
} while (0)
#define ANGLE_CL_VALIDATE_POINTER(EP, ...) \
do \
{ \
cl_int errorCode = Validate##EP(__VA_ARGS__); \
if (errorCode != CL_SUCCESS) \
{ \
return nullptr; \
} \
} while (0)
#endif // LIBANGLE_VALIDATIONCL_H_
......@@ -453,6 +453,7 @@ cl_includes = [
]
libangle_cl_headers = [
"src/libANGLE/CLBitField.h",
"src/libANGLE/CLBuffer.h",
"src/libANGLE/CLCommandQueue.h",
"src/libANGLE/CLContext.h",
......
......@@ -8,6 +8,7 @@
#ifndef LIBGLESV2_ENTRY_POINTS_CL_UTILS_H_
#define LIBGLESV2_ENTRY_POINTS_CL_UTILS_H_
#include "libANGLE/CLBitField.h"
#include "libANGLE/Debug.h"
#include "common/PackedCLEnums_autogen.h"
......@@ -25,9 +26,19 @@
namespace cl
{
// Handling only packed enums
template <typename Enum>
constexpr auto PackParam = FromCLenum<Enum>;
// Handling packed enums
template <typename PackedT, typename FromT>
typename std::enable_if_t<std::is_enum<PackedT>::value, PackedT> PackParam(FromT from)
{
return FromCLenum<PackedT>(from);
}
// Handling bit fields
template <typename PackedT, typename FromT>
typename std::enable_if_t<std::is_same<PackedT, BitField>::value, PackedT> PackParam(FromT from)
{
return PackedT(from);
}
void InitBackEnds(bool isIcd);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment