P4 to Git Change 1457530 by wchau@wchau_WIN_OCL_HSA on 2017/09/11 17:14:57
SWDEV-126884 - OCL 2.1 Platform APIs Affected files ... ... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/amdocl.def.in#17 edit ... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/amdocl.map#4 edit ... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/amdocl.map.in#19 edit ... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_command.cpp#14 edit ... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_context.cpp#56 edit ... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_execute.cpp#24 edit ... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_icd.cpp#30 edit ... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_icd_amd.h#20 edit ... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_program.cpp#42 edit ... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_svm.cpp#21 edit ... //depot/stg/opencl/drivers/opencl/api/opencl/khronos/headers/opencl2.1/CL/cl.h#5 edit ... //depot/stg/opencl/drivers/opencl/api/opencl/khronos/headers/opencl2.2/CL/cl.h#2 edit ... //depot/stg/opencl/drivers/opencl/runtime/platform/command.hpp#86 edit
이 커밋은 다음에 포함됨:
@@ -118,6 +118,16 @@ clEnqueueSVMMap
|
||||
clEnqueueSVMUnmap
|
||||
#endif
|
||||
|
||||
#if (OPENCL_MAJOR > 2) || (OPENCL_MAJOR == 2 && OPENCL_MINOR >= 1)
|
||||
clCloneKernel
|
||||
clCreateProgramWithIL
|
||||
clEnqueueSVMMigrateMem
|
||||
clGetDeviceAndHostTimer
|
||||
clGetHostTimer
|
||||
clGetKernelSubGroupInfo
|
||||
clSetDefaultDeviceCommandQueue
|
||||
#endif
|
||||
|
||||
#if !defined(WITH_LIGHTNING_COMPILER)
|
||||
aclCompilerInit
|
||||
aclCompilerFini
|
||||
|
||||
@@ -152,3 +152,14 @@ global:
|
||||
clEnqueueSVMMap;
|
||||
clEnqueueSVMUnmap;
|
||||
} OPENCL_1.2;
|
||||
|
||||
OPENCL_2.1 {
|
||||
global:
|
||||
clCloneKernel;
|
||||
clCreateProgramWithIL
|
||||
clEnqueueSVMMigrateMem
|
||||
clGetDeviceAndHostTimer
|
||||
clGetHostTimer
|
||||
clGetKernelSubGroupInfo
|
||||
clSetDefaultDeviceCommandQueue
|
||||
} OPENCL_2.0;
|
||||
|
||||
@@ -161,7 +161,13 @@ global:
|
||||
#if (OPENCL_MAJOR > 2) || (OPENCL_MAJOR == 2 && OPENCL_MINOR >= 1)
|
||||
OPENCL_2.1 {
|
||||
global:
|
||||
clCloneKernel;
|
||||
clCreateProgramWithIL;
|
||||
clEnqueueSVMMigrateMem;
|
||||
clGetDeviceAndHostTimer;
|
||||
clGetHostTimer;
|
||||
clGetKernelSubGroupInfo;
|
||||
clSetDefaultDeviceCommandQueue;
|
||||
} OPENCL_2.1;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -173,6 +173,67 @@ RUNTIME_ENTRY_RET(cl_command_queue, clCreateCommandQueue,
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
|
||||
/*! \brief Replaces the default command queue on the device
|
||||
*
|
||||
* \param context must be a valid OpenCL context.
|
||||
*
|
||||
* \param device must be a device associated with context.
|
||||
*
|
||||
* \param command_queue specifies the default command-queue.
|
||||
*
|
||||
* \reture One of the following values:
|
||||
* - CL_SUCCESS if the function executed successfully.
|
||||
* - CL_INVALID_CONTEXT if \a context is not a valid context.
|
||||
* - CL_INVALID_DEVICE if \a device is not a valid device or is not
|
||||
* associated with context.
|
||||
* - CL_INVALID_COMMAND_QUEUE if \a command_queue is not a valid command-
|
||||
* queue for device.
|
||||
*/
|
||||
RUNTIME_ENTRY(cl_int, clSetDefaultDeviceCommandQueue,
|
||||
(cl_context context, cl_device_id device, cl_command_queue command_queue)) {
|
||||
if (!is_valid(context)) {
|
||||
return CL_INVALID_CONTEXT;
|
||||
}
|
||||
|
||||
amd::Context& amdContext = *as_amd(context);
|
||||
amd::Device& amdDevice = *as_amd(device);
|
||||
amd::DeviceQueue* deviceQueue = as_amd(command_queue)->asDeviceQueue();
|
||||
|
||||
if (!is_valid(device) || !amdContext.containsDevice(&amdDevice)) {
|
||||
return CL_INVALID_DEVICE;
|
||||
}
|
||||
|
||||
if (!is_valid(command_queue)) {
|
||||
return CL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
|
||||
//TODO: implemente the set default device command queue logic
|
||||
LogWarning("Device support for clSetDefaultDeviceCommandQueue() has not been implemented");
|
||||
|
||||
#if 0
|
||||
// implementation of the set default device command queue logic - unverified
|
||||
|
||||
//TODO: Need to update the clGetCommandQueueInfo to support CL_QUEUE_DEVICE_DEFAULT
|
||||
//
|
||||
{
|
||||
amd::ScopedLock lock(amdContext.lock());
|
||||
|
||||
amd::DeviceQueue* queue = amdContext.defDeviceQueue(amdDevice);
|
||||
if (NULL != queue) {
|
||||
amdContext.removeDeviceQueue(amdDevice, queue);
|
||||
queue->release();
|
||||
}
|
||||
|
||||
amdContext.addDeviceQueue(amdDevice, deviceQueue, true);
|
||||
deviceQueue->retain();
|
||||
}
|
||||
#endif
|
||||
|
||||
return CL_INVALID_VALUE;
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
|
||||
/*! \brief Increment the \a command_queue reference count.
|
||||
*
|
||||
* \return One of the following values:
|
||||
|
||||
@@ -477,7 +477,7 @@ CL_API_ENTRY void* CL_API_CALL clGetExtensionFunctionAddress(const char* func_na
|
||||
CL_EXTENSION_ENTRYPOINT_CHECK(clConvertImageAMD);
|
||||
CL_EXTENSION_ENTRYPOINT_CHECK(clCreateBufferFromImageAMD);
|
||||
#if defined(cl_khr_il_program) || defined(CL_VERSION_2_1)
|
||||
CL_EXTENSION_ENTRYPOINT_CHECK(clCreateProgramWithILKHR)
|
||||
CL_EXTENSION_ENTRYPOINT_CHECK2(clCreateProgramWithILKHR,clCreateProgramWithIL);
|
||||
#endif // defined(cl_khr_il_program) || defined(CL_VERSION_2_1)
|
||||
#if cl_amd_liquid_flash
|
||||
CL_EXTENSION_ENTRYPOINT_CHECK(clCreateSsgFileObjectAMD);
|
||||
@@ -522,7 +522,7 @@ CL_API_ENTRY void* CL_API_CALL clGetExtensionFunctionAddress(const char* func_na
|
||||
CL_EXTENSION_ENTRYPOINT_CHECK(clGetPlaneFromImageAMD);
|
||||
#endif //_WIN32
|
||||
#if defined(cl_khr_sub_groups) || defined(CL_VERSION_2_1)
|
||||
CL_EXTENSION_ENTRYPOINT_CHECK(clGetKernelSubGroupInfoKHR);
|
||||
CL_EXTENSION_ENTRYPOINT_CHECK2(clGetKernelSubGroupInfoKHR,clGetKernelSubGroupInfo);
|
||||
#endif // defined(cl_khr_sub_groups) || defined(CL_VERSION_2_1)
|
||||
#if cl_amd_liquid_flash
|
||||
CL_EXTENSION_ENTRYPOINT_CHECK(clGetSsgFileObjectInfoAMD);
|
||||
|
||||
@@ -924,6 +924,100 @@ RUNTIME_ENTRY(cl_int, clGetEventProfilingInfo,
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
|
||||
/*! \brief Returns a reasonably synchronized pair of timestamps from the device
|
||||
* timer and the host timer as seen by device.
|
||||
*
|
||||
* \param device a device returned by clGetDeviceIDs.
|
||||
*
|
||||
* \param device_timestamp will be updated with the value of the current timer
|
||||
* in nanoseconds. The resolution of the timer is the same as the device
|
||||
* profiling timer returned by clGetDeviceInfo and the
|
||||
* CL_DEVICE_PROFILING_TIMER_RESOLUTION query.
|
||||
*
|
||||
* \param host_timestamp will be updated with the value of the current timer
|
||||
* in nanoseconds at the closest possible point in time to that at which
|
||||
* device_timer was returned. The resolution of the timer may be queried
|
||||
* via clGetPlatformInfo and the flag CL_PLATFORM_HOST_TIMER_RESOLUTION.
|
||||
*
|
||||
* Returns a reasonably synchronized pair of timestamps from the device
|
||||
* timer and the host timer as seen by device. Implementations may need
|
||||
* to execute this query with a high latency in order to provide reasonable
|
||||
* synchronization of the timestamps. The host timestamp and device timestamp
|
||||
* returned by this function and clGetHostTimer each have an implementation
|
||||
* defined timebase. The timestamps will always be in their respective timebases
|
||||
* regardless of which query function is used. The timestamp returned from
|
||||
* clGetEventProfilingInfo for an event on a device and a device timestamp
|
||||
* queried from the same device will always be in the same timebase.
|
||||
*
|
||||
* \return One of the following values:
|
||||
* - CL_SUCCESS if a time value in host_timestamp is provided
|
||||
* - CL_INVALID_DEVICE if device is not a valid OpenCL device.
|
||||
* - CL_INVALID_VALUE if host_timestamp is NULL.
|
||||
* - CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
|
||||
* by the OpenCL implementation on the device.
|
||||
* - CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources required
|
||||
* by the OpenCL implementation on the host.
|
||||
*
|
||||
*/
|
||||
RUNTIME_ENTRY(cl_int, clGetDeviceAndHostTimer,
|
||||
(cl_device_id device, cl_ulong * device_timestamp,
|
||||
cl_ulong * host_timestamp)) {
|
||||
|
||||
if (!is_valid(device)) {
|
||||
return CL_INVALID_DEVICE;
|
||||
}
|
||||
|
||||
// TODO: Implement get device and host timer logic
|
||||
LogWarning("Device support for clGetDeviceAndHostTimer() has not been implemented.");
|
||||
|
||||
return CL_INVALID_VALUE;
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
|
||||
/*! \brief Return the current value of the host clock as seen by device.
|
||||
*
|
||||
* \param device a device returned by clGetDeviceIDs.
|
||||
*
|
||||
* \param host_timestamp will be updated with the value of the current timer
|
||||
* in nanoseconds. The resolution of the timer may be queried via
|
||||
* clGetPlatformInfo and the flag CL_PLATFORM_HOST_TIMER_RESOLUTION.
|
||||
*
|
||||
* Return the current value of the host clock as seen by device. This value
|
||||
* is in the same timebase as the host_timestamp returned from
|
||||
* clGetDeviceAndHostTimer. The implementation will return with as low a
|
||||
* latency as possible to allow a correlation with a subsequent application
|
||||
* sampled time. The host timestamp and device timestamp returned by this
|
||||
* function and clGetDeviceAndHostTimer each have an implementation defined
|
||||
* timebase. The timestamps will always be in their respective timebases
|
||||
* regardless of which query function is used. The timestamp returned from
|
||||
* clGetEventProfilingInfo for an event on a device and a device timestamp
|
||||
* queried from the same device will always be in the same timebase.
|
||||
*
|
||||
* \return One of the following values:
|
||||
*
|
||||
* - CL_SUCCESS if a time value in host_timestamp is provided
|
||||
* - CL_INVALID_DEVICE if device is not a valid OpenCL device.
|
||||
* - CL_INVALID_VALUE if host_timestamp is NULL.
|
||||
* - CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
|
||||
* by the OpenCL implementation on the device.
|
||||
* - CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources required
|
||||
* by the OpenCL implementation on the host.
|
||||
*
|
||||
*/
|
||||
RUNTIME_ENTRY(cl_int, clGetHostTimer,
|
||||
(cl_device_id device, cl_ulong * host_timestamp)) {
|
||||
|
||||
if (!is_valid(device)) {
|
||||
return CL_INVALID_DEVICE;
|
||||
}
|
||||
|
||||
// TODO: Implement get host timer logic
|
||||
LogWarning("Device support for clGetHostTimer() has not been implemented.");
|
||||
|
||||
return CL_INVALID_VALUE;
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
|
||||
/*! @}
|
||||
* \addtogroup CL_FlushFinish Flush and Finish
|
||||
* @{
|
||||
|
||||
@@ -99,8 +99,14 @@ KHRicdVendorDispatch amd::ICDDispatchedObject::icdVendorDispatch_[] = {
|
||||
clCreateCommandQueueWithProperties, clCreatePipe, clGetPipeInfo, clSVMAlloc, clSVMFree,
|
||||
clEnqueueSVMFree, clEnqueueSVMMemcpy, clEnqueueSVMMemFill, clEnqueueSVMMap, clEnqueueSVMUnmap,
|
||||
clCreateSamplerWithProperties, clSetKernelArgSVMPointer, clSetKernelExecInfo,
|
||||
|
||||
clGetKernelSubGroupInfoKHR}};
|
||||
clGetKernelSubGroupInfo,
|
||||
clCloneKernel,
|
||||
clCreateProgramWithIL,
|
||||
clEnqueueSVMMigrateMem,
|
||||
clGetDeviceAndHostTimer,
|
||||
clGetHostTimer,
|
||||
clGetKernelSubGroupInfo,
|
||||
clSetDefaultDeviceCommandQueue}};
|
||||
|
||||
#if defined(ATI_OS_WIN)
|
||||
#include <Shlwapi.h>
|
||||
|
||||
@@ -154,7 +154,7 @@ typedef cl_program(CL_API_CALL* clCreateProgramWithSource_fn)(
|
||||
const size_t* /* lengths */, cl_int* /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
|
||||
|
||||
extern CL_API_ENTRY cl_program CL_API_CALL
|
||||
clCreateProgramWithILKHR(cl_context /* context */,
|
||||
clCreateProgramWithIL(cl_context /* context */,
|
||||
const void * /* strings */, size_t /* lengths */,
|
||||
cl_int * /* errcode_ret */) CL_EXT_SUFFIX__VERSION_2_0;
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@ RUNTIME_EXIT
|
||||
*
|
||||
* \version 1.0r33
|
||||
*/
|
||||
RUNTIME_ENTRY_RET(cl_program, clCreateProgramWithILKHR,
|
||||
RUNTIME_ENTRY_RET(cl_program, clCreateProgramWithIL,
|
||||
(cl_context context, const void* il, size_t length, cl_int* errcode_ret)) {
|
||||
if (!is_valid(context)) {
|
||||
*not_null(errcode_ret) = CL_INVALID_CONTEXT;
|
||||
@@ -1291,6 +1291,78 @@ RUNTIME_ENTRY(cl_int, clReleaseKernel, (cl_kernel kernel)) {
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
|
||||
/*! \brief Makes a shallow copy of the kernel object, its arguments and any
|
||||
* information passed to the kernel object using \a clSetKernelExecInfo. If
|
||||
* the kernel object was ready to be enqueued before copying it, the clone of
|
||||
* the kernel object is ready to enqueue.
|
||||
*
|
||||
* \param source_kernel is a valid cl_kernel object that will be copied.
|
||||
* source_kernel will not be modified in any way by this function.
|
||||
*
|
||||
* \param errcode_ret will be assigned an appropriate error code. If
|
||||
* errcode_ret is NULL, no error code is returned.
|
||||
*
|
||||
* \return a valid non-zero kernel object and errcode_ret is set to
|
||||
* CL_SUCCESS if the kernel is successfully copied. Otherwise it returns a
|
||||
* NULL value with one of the following error values returned in errcode_ret:
|
||||
* - CL_INVALID_KERNEL if kernel is not a valid kernel object.
|
||||
* - CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
|
||||
* by the OpenCL implementation on the device.
|
||||
* - CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
|
||||
* required by the OpenCL implementation on the host.
|
||||
*
|
||||
* \version 2.1r01
|
||||
*/
|
||||
RUNTIME_ENTRY_RET(cl_kernel, clCloneKernel,
|
||||
(cl_kernel source_kernel, cl_int* errcode_ret)) {
|
||||
if (!is_valid(source_kernel)) {
|
||||
*not_null(errcode_ret) = CL_INVALID_KERNEL;
|
||||
return (cl_kernel)0;
|
||||
}
|
||||
|
||||
amd::Kernel* srcKernel = as_amd(source_kernel);
|
||||
amd::Program* program = &(srcKernel->program());
|
||||
const char* kernelName = srcKernel->name().c_str();
|
||||
const amd::Symbol* symbol = program->findSymbol(kernelName);
|
||||
if (symbol == NULL) {
|
||||
*not_null(errcode_ret) = CL_INVALID_KERNEL_NAME;
|
||||
return (cl_kernel)0;
|
||||
}
|
||||
|
||||
amd::Kernel* kernel = new amd::Kernel(*program, *symbol, kernelName);
|
||||
if (kernel == NULL) {
|
||||
*not_null(errcode_ret) = CL_OUT_OF_HOST_MEMORY;
|
||||
return (cl_kernel)0;
|
||||
}
|
||||
|
||||
//TODO: implemente the clone kernel logic
|
||||
LogWarning("Device support for clCloneKernel() has not been implemented");
|
||||
|
||||
#if 0
|
||||
// clone kernel logic - unverified
|
||||
|
||||
// clone the parameter values_, defined_, svmBound_ arrays
|
||||
amd::KernelParameters* srcParameters = &(srcKernel->parameters());
|
||||
amd::KernelParameters* parameters = &(kernel->parameters());
|
||||
const amd::KernelSignature& signature = kernel->signature();
|
||||
size_t size = signature.paramsSize() + signature.numParameters() * sizeof(bool) * 2;
|
||||
::memcpy(parameters->values(), srcParameters->values(), size);
|
||||
|
||||
// clone the exec info
|
||||
parameters->setExecInfoOffset(srcParameters->getExecInfoOffset());
|
||||
|
||||
parameters->addSvmPtr(srcParameters->getExecSvmPtr(), srcParameters->getNumberOfSvmPtr());
|
||||
parameters->setSvmSystemPointersSupport(srcParameters->getSvmSystemPointersSupport());
|
||||
parameters->setValidated(srcParameters->getValidated());
|
||||
parameters->setExecNewVcop(srcParameters->getExecNewVcop());
|
||||
parameters->setExecPfpaVcop(srcParameters->getExecPfpaVcop());
|
||||
#endif
|
||||
|
||||
*not_null(errcode_ret) = CL_INVALID_VALUE;
|
||||
return as_cl(kernel);
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
|
||||
/*! @}
|
||||
* \addtogroup CL_SettingArgs
|
||||
* @{
|
||||
@@ -1662,7 +1734,7 @@ RUNTIME_EXIT
|
||||
*
|
||||
* \param param_name specifies the information to query. The list of supported
|
||||
* param_name types and the information returned in param_value by
|
||||
* clGetKernelSubGroupInfoKHR is described in the table below.
|
||||
* clGetKernelSubGroupInfo is described in the table below.
|
||||
*
|
||||
* \param input_value_size is used to specify the size in bytes of memory
|
||||
* pointed to by input_value. This size must be == size of input type as
|
||||
@@ -1702,7 +1774,7 @@ RUNTIME_EXIT
|
||||
*
|
||||
* \version 2.0r12
|
||||
*/
|
||||
RUNTIME_ENTRY(cl_int, clGetKernelSubGroupInfoKHR,
|
||||
RUNTIME_ENTRY(cl_int, clGetKernelSubGroupInfo,
|
||||
(cl_kernel kernel, cl_device_id device, cl_kernel_sub_group_info param_name,
|
||||
size_t input_value_size, const void* input_value, size_t param_value_size,
|
||||
void* param_value, size_t* param_value_size_ret)) {
|
||||
@@ -1756,6 +1828,12 @@ RUNTIME_ENTRY(cl_int, clGetKernelSubGroupInfoKHR,
|
||||
: numSubGroups,
|
||||
param_value_size, param_value, param_value_size_ret);
|
||||
}
|
||||
case CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT:
|
||||
case CL_KERNEL_MAX_NUM_SUB_GROUPS:
|
||||
case CL_KERNEL_COMPILE_NUM_SUB_GROUPS:
|
||||
//TODO: implemente the kernel subgroup info query
|
||||
LogWarning("Device support for clGetKernelSubGroupInfo() query has not been implemented.");
|
||||
return CL_INVALID_VALUE;
|
||||
default:
|
||||
return CL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
@@ -1036,6 +1036,172 @@ RUNTIME_ENTRY(cl_int, clSetKernelExecInfo, (cl_kernel kernel, cl_kernel_exec_inf
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
|
||||
/*! \brief Enqueues a command to indicate which device a set of ranges of SVM
|
||||
* allocations should be associated with. Once the event returned by
|
||||
* \a clEnqueueSVMMigrateMem has become CL_COMPLETE, the ranges specified by
|
||||
* svm pointers and sizes have been successfully migrated to the device
|
||||
* associated with command queue.
|
||||
* The user is responsible for managing the event dependencies associated with
|
||||
* this command in order to avoid overlapping access to SVM allocations.
|
||||
* Improperly specified event dependencies passed to clEnqueueSVMMigrateMem
|
||||
* could result in undefined results
|
||||
*
|
||||
* \param command_queue is a valid host command queue. The specified set of
|
||||
* allocation ranges will be migrated to the OpenCL device associated with
|
||||
* command_queue.
|
||||
*
|
||||
* \param num_svm_pointers is the number of pointers in the specified
|
||||
* svm_pointers array, and the number of sizes in the sizes array, if sizes
|
||||
* is not NULL.
|
||||
*
|
||||
* \param svm_pointers is a pointer to an array of pointers. Each pointer in
|
||||
* this array must be within an allocation produced by a call to clSVMAlloc.
|
||||
*
|
||||
* \param sizes is an array of sizes. The pair svm_pointers[i] and sizes[i]
|
||||
* together define the starting address and number of bytes in a range to be
|
||||
* migrated. sizes may be NULL indicating that every allocation containing
|
||||
* any svm_pointer[i] is to be migrated. Also, if sizes[i] is zero, then the
|
||||
* entire allocation containing svm_pointer[i] is migrated.
|
||||
*
|
||||
* \param flags is a bit-field that is used to specify migration options.
|
||||
* Table 5.12 describes the possible values for flags.
|
||||
*
|
||||
* \param num_events_in_wait_list specifies the number of event objects in
|
||||
* \a event_wait_list.
|
||||
*
|
||||
* \param event_wait_list specifies events that need to complete before this
|
||||
* particular command can be executed. If event_wait_list is NULL, then this
|
||||
* particular command does not wait on any event to complete. If
|
||||
* event_wait_list is NULL, num_events_in_wait_list must be 0. If
|
||||
* event_wait_list is not NULL, the list of events pointed to by
|
||||
* event_wait_list must be valid and num_events_in_wait_list must be greater
|
||||
* than 0. The events specified in event_wait_list act as synchronization
|
||||
* points. The context associated with events in event_wait_list and
|
||||
* command_queue must be the same. The memory associated with
|
||||
* event_wait_list can be reused or freed after the function returns.
|
||||
*
|
||||
* \param event an returned event object that identifies this particular write
|
||||
* command and can be used to query or queue a wait for this particular
|
||||
* command to complete. event can be NULL in which case it will not be
|
||||
* possible for the application to query the status of this command or queue
|
||||
* another command that waits for this command to complete. If the
|
||||
* event_wait_list and the event arguments are not NULL, the event argument
|
||||
* should not refer to an element of the event_wait_list array.
|
||||
*
|
||||
* \return One of the following values:
|
||||
* - CL_SUCCESS if the function is executed successfully
|
||||
* - CL_INVALID_COMMAND_QUEUE if \a command_queue is not a valid command-queue
|
||||
* - CL_INVALID_VALUE if num_svm_pointers is zero or svm_pointers is NULL
|
||||
* - CL_INVALID_VALUE if sizes[i] is non-zero range [svm_pointers[i],
|
||||
* svm_pointers[i]+sizes[i]) is not contained within an existing clSVMAlloc
|
||||
* allocation
|
||||
* - CL_INVALID_EVENT_WAIT_LIST if event_wait_list is NULL and
|
||||
* num_events_in_wait_list > 0, or event_wait_list is not NULL and
|
||||
* num_events_in_wait_list is 0, or if event objects in event_wait_list are
|
||||
* not valid events
|
||||
* - CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
|
||||
* by the OpenCL implementation on the device.
|
||||
* - CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources required
|
||||
* by the OpenCL implementation on the host.
|
||||
*
|
||||
* \version 2.1r00
|
||||
*/
|
||||
RUNTIME_ENTRY(cl_int, clEnqueueSVMMigrateMem,
|
||||
(cl_command_queue command_queue, cl_uint num_svm_pointers, const void **svm_pointers,
|
||||
const size_t *size, cl_mem_migration_flags flags, cl_uint num_events_in_wait_list,
|
||||
const cl_event* event_wait_list, cl_event* event)) {
|
||||
|
||||
if (!is_valid(command_queue)) {
|
||||
return CL_INVALID_COMMAND_QUEUE;
|
||||
}
|
||||
|
||||
amd::HostQueue* queue = as_amd(command_queue)->asHostQueue();
|
||||
if (NULL == queue) {
|
||||
return CL_INVALID_COMMAND_QUEUE;
|
||||
}
|
||||
amd::HostQueue& hostQueue = *queue;
|
||||
|
||||
if (num_svm_pointers == 0) {
|
||||
LogWarning("invalid parameter \"num_svm_pointers = 0\"");
|
||||
return CL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if (svm_pointers == NULL) {
|
||||
LogWarning("invalid parameter \"svm_pointers = NULL\"");
|
||||
return CL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
for (cl_uint i = 0; i < num_svm_pointers; i++) {
|
||||
if (svm_pointers[i] == NULL) {
|
||||
LogWarning("Null pointers are not allowed");
|
||||
return CL_INVALID_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & ~(CL_MIGRATE_MEM_OBJECT_HOST | CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED)) {
|
||||
LogWarning("Invalid flag is specified");
|
||||
return CL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
//TODO: implemente the svm migration memory logic
|
||||
LogWarning("Device support for clEnqueueSVMMigrateMem() has not been implemented");
|
||||
|
||||
#if 0
|
||||
// implementation of the svm migration memory logic - unverified
|
||||
|
||||
for (int i = 0; i < num_svm_pointers; i++) {
|
||||
const void* svm_ptr = svm_pointers[i];
|
||||
|
||||
amd::Memory* svmMem = amd::SvmManager::FindSvmBuffer(svm_ptr);
|
||||
if (NULL != svmMem) {
|
||||
// make sure the context is the same as the context of creation of svm space
|
||||
if (hostQueue.context() != svmMem->getContext()) {
|
||||
LogWarning("different contexts");
|
||||
return CL_INVALID_CONTEXT;
|
||||
}
|
||||
|
||||
// Make sure the specified size[i] is within a valid range
|
||||
size_t svm_size = (size == NULL) ? 0 : size[i];
|
||||
size_t offset = reinterpret_cast<uintptr_t>(svm_ptr) - reinterpret_cast<uintptr_t>(svmMem->getSvmPtr());
|
||||
if (offset < 0 || (offset + svm_size) > svmMem->getSize()) {
|
||||
LogWarning("wrong svm address ");
|
||||
return CL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
// Make sure we have memory for the command execution
|
||||
device::Memory* mem = svmMem->getDeviceMemory(queue->device());
|
||||
if (NULL == mem) {
|
||||
LogPrintfError("Can't allocate memory size - 0x%08X bytes!", svmMem->getSize());
|
||||
return CL_OUT_OF_RESOURCES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
amd::Command::EventWaitList eventWaitList;
|
||||
cl_int err = amd::clSetEventWaitList(eventWaitList, hostQueue.context(), num_events_in_wait_list,
|
||||
event_wait_list);
|
||||
if (err != CL_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
amd::Command* command = new amd::SvmMigrateMemCommand(hostQueue, eventWaitList, num_svm_pointers,
|
||||
svm_pointers, size, flags);
|
||||
|
||||
if (command == NULL) {
|
||||
return CL_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
command->enqueue();
|
||||
|
||||
*not_null(event) = as_cl(&command->event());
|
||||
if (event == NULL) {
|
||||
command->release();
|
||||
}
|
||||
#endif
|
||||
|
||||
return CL_INVALID_VALUE;
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
/*! @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -637,6 +637,7 @@ typedef struct _cl_buffer_region {
|
||||
#define CL_COMMAND_SVM_MEMFILL 0x120B
|
||||
#define CL_COMMAND_SVM_MAP 0x120C
|
||||
#define CL_COMMAND_SVM_UNMAP 0x120D
|
||||
#define CL_COMMAND_SVM_MIGRATE_MEM 0x120E
|
||||
|
||||
/* command execution status */
|
||||
#define CL_COMPLETE 0x0
|
||||
|
||||
@@ -642,6 +642,7 @@ typedef struct _cl_buffer_region {
|
||||
#define CL_COMMAND_SVM_MEMFILL 0x120B
|
||||
#define CL_COMMAND_SVM_MAP 0x120C
|
||||
#define CL_COMMAND_SVM_UNMAP 0x120D
|
||||
#define CL_COMMAND_SVM_MIGRATE_MEM 0x120E
|
||||
|
||||
/* command execution status */
|
||||
#define CL_COMPLETE 0x0
|
||||
|
||||
새 이슈에서 참조
사용자 차단