diff --git a/projects/clr/opencl/api/opencl/amdocl/amdocl.def.in b/projects/clr/opencl/api/opencl/amdocl/amdocl.def.in index cc631e3ca2..78df2030fd 100644 --- a/projects/clr/opencl/api/opencl/amdocl/amdocl.def.in +++ b/projects/clr/opencl/api/opencl/amdocl/amdocl.def.in @@ -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 diff --git a/projects/clr/opencl/api/opencl/amdocl/amdocl.map b/projects/clr/opencl/api/opencl/amdocl/amdocl.map index 4186970f4a..8e45fba1c0 100644 --- a/projects/clr/opencl/api/opencl/amdocl/amdocl.map +++ b/projects/clr/opencl/api/opencl/amdocl/amdocl.map @@ -152,3 +152,14 @@ global: clEnqueueSVMMap; clEnqueueSVMUnmap; } OPENCL_1.2; + +OPENCL_2.1 { +global: + clCloneKernel; + clCreateProgramWithIL + clEnqueueSVMMigrateMem + clGetDeviceAndHostTimer + clGetHostTimer + clGetKernelSubGroupInfo + clSetDefaultDeviceCommandQueue +} OPENCL_2.0; diff --git a/projects/clr/opencl/api/opencl/amdocl/amdocl.map.in b/projects/clr/opencl/api/opencl/amdocl/amdocl.map.in index 8861832f92..507d14b7d6 100644 --- a/projects/clr/opencl/api/opencl/amdocl/amdocl.map.in +++ b/projects/clr/opencl/api/opencl/amdocl/amdocl.map.in @@ -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 diff --git a/projects/clr/opencl/api/opencl/amdocl/cl_command.cpp b/projects/clr/opencl/api/opencl/amdocl/cl_command.cpp index 82dcdf8025..c7ccfb4ce4 100644 --- a/projects/clr/opencl/api/opencl/amdocl/cl_command.cpp +++ b/projects/clr/opencl/api/opencl/amdocl/cl_command.cpp @@ -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: diff --git a/projects/clr/opencl/api/opencl/amdocl/cl_context.cpp b/projects/clr/opencl/api/opencl/amdocl/cl_context.cpp index 2148e4b2b1..b74e32b094 100644 --- a/projects/clr/opencl/api/opencl/amdocl/cl_context.cpp +++ b/projects/clr/opencl/api/opencl/amdocl/cl_context.cpp @@ -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); diff --git a/projects/clr/opencl/api/opencl/amdocl/cl_execute.cpp b/projects/clr/opencl/api/opencl/amdocl/cl_execute.cpp index 32488871f8..b6d1bf2de0 100644 --- a/projects/clr/opencl/api/opencl/amdocl/cl_execute.cpp +++ b/projects/clr/opencl/api/opencl/amdocl/cl_execute.cpp @@ -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 * @{ diff --git a/projects/clr/opencl/api/opencl/amdocl/cl_icd.cpp b/projects/clr/opencl/api/opencl/amdocl/cl_icd.cpp index 2174e7fdd0..bbf19f7d9e 100644 --- a/projects/clr/opencl/api/opencl/amdocl/cl_icd.cpp +++ b/projects/clr/opencl/api/opencl/amdocl/cl_icd.cpp @@ -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 diff --git a/projects/clr/opencl/api/opencl/amdocl/cl_icd_amd.h b/projects/clr/opencl/api/opencl/amdocl/cl_icd_amd.h index 26a167652e..d5ce82349c 100644 --- a/projects/clr/opencl/api/opencl/amdocl/cl_icd_amd.h +++ b/projects/clr/opencl/api/opencl/amdocl/cl_icd_amd.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; diff --git a/projects/clr/opencl/api/opencl/amdocl/cl_program.cpp b/projects/clr/opencl/api/opencl/amdocl/cl_program.cpp index 34fff72907..8a7229dc6e 100644 --- a/projects/clr/opencl/api/opencl/amdocl/cl_program.cpp +++ b/projects/clr/opencl/api/opencl/amdocl/cl_program.cpp @@ -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; } diff --git a/projects/clr/opencl/api/opencl/amdocl/cl_svm.cpp b/projects/clr/opencl/api/opencl/amdocl/cl_svm.cpp index a602c736d8..3416beeb92 100644 --- a/projects/clr/opencl/api/opencl/amdocl/cl_svm.cpp +++ b/projects/clr/opencl/api/opencl/amdocl/cl_svm.cpp @@ -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(svm_ptr) - reinterpret_cast(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 /*! @} * @} */ diff --git a/projects/clr/opencl/api/opencl/khronos/headers/opencl2.1/CL/cl.h b/projects/clr/opencl/api/opencl/khronos/headers/opencl2.1/CL/cl.h index 4dab53a935..706e944545 100644 --- a/projects/clr/opencl/api/opencl/khronos/headers/opencl2.1/CL/cl.h +++ b/projects/clr/opencl/api/opencl/khronos/headers/opencl2.1/CL/cl.h @@ -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 diff --git a/projects/clr/opencl/api/opencl/khronos/headers/opencl2.2/CL/cl.h b/projects/clr/opencl/api/opencl/khronos/headers/opencl2.2/CL/cl.h index 1e164eb839..43ac8ab1ea 100644 --- a/projects/clr/opencl/api/opencl/khronos/headers/opencl2.2/CL/cl.h +++ b/projects/clr/opencl/api/opencl/khronos/headers/opencl2.2/CL/cl.h @@ -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