499 righe
20 KiB
C++
499 righe
20 KiB
C++
//
|
|
// Copyright (c) 2009 Advanced Micro Devices, Inc. All rights reserved.
|
|
//
|
|
#include "cl_common.hpp"
|
|
#include "cl_thread_trace_amd.h"
|
|
#include "platform/context.hpp"
|
|
#include "platform/command.hpp"
|
|
#include "platform/threadtrace.hpp"
|
|
#include <cstring>
|
|
#include <vector>
|
|
|
|
/*! \addtogroup API
|
|
* @{
|
|
*
|
|
* \addtogroup AMD_Extensions
|
|
* @{
|
|
*
|
|
*/
|
|
|
|
/*! \brief Creates a new HW threadTrace
|
|
*
|
|
* \param device must be a valid OpenCL device.
|
|
*
|
|
* \param threadTrace the created cl_threadtrace_amd object
|
|
*
|
|
* \param errcode_ret A non zero value if OpenCL failed to create cl_threadtrace_amd
|
|
* - CL_SUCCESS if the function is executed successfully.
|
|
* - CL_INVALID_DEVICE if the specified context is invalid.
|
|
* - CL_INVALID_OPERATION if we couldn't create the object
|
|
*
|
|
* \return Created cl_threadtrace_amd object
|
|
*/
|
|
RUNTIME_ENTRY_RET(cl_threadtrace_amd, clCreateThreadTraceAMD, (
|
|
cl_device_id device,
|
|
cl_int* errcode_ret))
|
|
{
|
|
// Make sure we have a valid device object
|
|
if (!is_valid(device)) {
|
|
*not_null(errcode_ret) = CL_INVALID_DEVICE;
|
|
return NULL;
|
|
}
|
|
|
|
// Create the device thread trace object
|
|
amd::ThreadTrace* threadTrace =
|
|
new amd::ThreadTrace(*as_amd(device));
|
|
|
|
if (threadTrace == NULL) {
|
|
*not_null(errcode_ret) = CL_INVALID_OPERATION;
|
|
return NULL;
|
|
}
|
|
|
|
*not_null(errcode_ret) = CL_SUCCESS;
|
|
return as_cl(threadTrace);
|
|
}
|
|
RUNTIME_EXIT
|
|
|
|
///*! \brief Destroy a threadTrace object.
|
|
// *
|
|
// * \param threadTrace the cl_threadtrace_amd object for release
|
|
// *
|
|
// * \return A non zero value if OpenCL failed to release cl_threadtrace_amd
|
|
// * - CL_SUCCESS if the function is executed successfully.
|
|
// * - CL_INVALID_OPERATION if we failed to release the object
|
|
// */
|
|
RUNTIME_ENTRY(cl_int, clReleaseThreadTraceAMD, (
|
|
cl_threadtrace_amd threadTrace))
|
|
{
|
|
if (!is_valid(threadTrace)) {
|
|
return CL_INVALID_OPERATION;
|
|
}
|
|
as_amd(threadTrace)->release();
|
|
return CL_SUCCESS;
|
|
}
|
|
RUNTIME_EXIT
|
|
//
|
|
// *! \brief Increments the cl_threadtrace_amd object reference count.
|
|
// *
|
|
// * \param threadTrace the cl_threadtrace_amd object for retain
|
|
// *
|
|
// * \return A non zero value if OpenCL failed to retain cl_threadtrace_amd
|
|
// * - CL_SUCCESS if the function is executed successfully.
|
|
// * - CL_INVALID_OPERATION if we failed to release the object
|
|
// */
|
|
RUNTIME_ENTRY(cl_int, clRetainThreadTraceAMD, (
|
|
cl_threadtrace_amd threadTrace))
|
|
{
|
|
if (!is_valid(threadTrace)) {
|
|
return CL_INVALID_OPERATION;
|
|
}
|
|
as_amd(threadTrace)->retain();
|
|
return CL_SUCCESS;
|
|
}
|
|
RUNTIME_EXIT
|
|
|
|
//
|
|
// *! \brief Sets the cl_threadtrace_amd object configuration parameter.
|
|
// *
|
|
// * \param thread_trace the cl_threadtrace_amd object to set configuration parameter
|
|
// *
|
|
// * \param config_param the cl_thread_trace_param
|
|
// *
|
|
// * \param param_value corresponding to configParam
|
|
// *
|
|
// * \return A non zero value if OpenCL failed to set threadTrace buffer parameter
|
|
// * - CL_INVALID_VALUE if the thread_trace is invalid thread trace object.
|
|
// * - CL_INVALID_VALUE if the invalid config_param or param_value enum values , are used.
|
|
// * - 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.
|
|
// */
|
|
RUNTIME_ENTRY(cl_int, clSetThreadTraceParamAMD,(cl_threadtrace_amd thread_trace ,
|
|
cl_thread_trace_param config_param ,
|
|
cl_uint param_value ))
|
|
{
|
|
if (!is_valid(thread_trace)) {
|
|
return CL_INVALID_OPERATION;
|
|
}
|
|
switch (config_param) {
|
|
case CL_THREAD_TRACE_PARAM_TOKEN_MASK:
|
|
if (param_value > CL_THREAD_TRACE_TOKEN_MASK_ALL_SI) {
|
|
return CL_INVALID_VALUE;
|
|
}
|
|
as_amd(thread_trace)->setTokenMask(param_value);
|
|
break;
|
|
case CL_THREAD_TRACE_PARAM_REG_MASK:
|
|
if (param_value > CL_THREAD_TRACE_REG_MASK_ALL_SI) {
|
|
return CL_INVALID_VALUE;
|
|
}
|
|
as_amd(thread_trace)->setRegMask(param_value);
|
|
break;
|
|
case CL_THREAD_TRACE_PARAM_VM_ID_MASK:
|
|
if (param_value > CL_THREAD_TRACE_VM_ID_MASK_SINGLE_DETAIL) {
|
|
return CL_INVALID_VALUE;
|
|
}
|
|
as_amd(thread_trace)->setVmIdMask(param_value);
|
|
break;
|
|
case CL_THREAD_TRACE_PARAM_INSTRUCTION_MASK:
|
|
if (param_value > CL_THREAD_TRACE_INST_MASK_IMMEDIATE_CI) {
|
|
return CL_INVALID_VALUE;
|
|
}
|
|
as_amd(thread_trace)->setInstMask(param_value);
|
|
break;
|
|
case CL_THREAD_TRACE_PARAM_COMPUTE_UNIT_TARGET:
|
|
as_amd(thread_trace)->setCU(param_value);
|
|
break;
|
|
case CL_THREAD_TRACE_PARAM_SHADER_ARRAY_TARGET:
|
|
as_amd(thread_trace)->setSH(param_value);
|
|
break;
|
|
case CL_THREAD_TRACE_PARAM_SIMD_MASK:
|
|
as_amd(thread_trace)->setSIMD(param_value);
|
|
break;
|
|
case CL_THREAD_TRACE_PARAM_USER_DATA:
|
|
as_amd(thread_trace)->setUserData(param_value);
|
|
break;
|
|
case CL_THREAD_TRACE_PARAM_CAPTURE_MODE:
|
|
if (param_value > CL_THREAD_TRACE_CAPTURE_SELECT_DETAIL) {
|
|
return CL_INVALID_VALUE;
|
|
}
|
|
as_amd(thread_trace)->setCaptureMode(param_value);
|
|
break;
|
|
case CL_THREAD_TRACE_PARAM_IS_WRAPPED:
|
|
as_amd(thread_trace)->setIsWrapped(true);
|
|
break;
|
|
case CL_THREAD_TRACE_PARAM_RANDOM_SEED:
|
|
as_amd(thread_trace)->setRandomSeed(param_value);
|
|
break;
|
|
}
|
|
return CL_SUCCESS;
|
|
}
|
|
RUNTIME_EXIT
|
|
|
|
/*! \brief Get specific information about the OpenCL Thread Trace.
|
|
*
|
|
* \param threadTrace_info_param is an enum that identifies the Thread Trace information being
|
|
* queried.
|
|
*
|
|
* \param param_value is a pointer to memory location where appropriate values
|
|
* for a given \a threadTrace_info_param will be returned. If \a param_value is NULL,
|
|
* it is ignored.
|
|
*
|
|
* \param param_value_size specifies the size in bytes of memory pointed to by
|
|
* \a param_value. This size in bytes must be >= size of return type.
|
|
*
|
|
* \param param_value_size_ret returns the actual size in bytes of data being
|
|
* queried by param_value. If \a param_value_size_ret is NULL, it is ignored.
|
|
*
|
|
* \return One of the following values:
|
|
* CL_INVALID_OPERATION if cl_threadtrace_amd object is not valid
|
|
* - CL_INVALID_VALUE if \a param_name is not one of the supported
|
|
* values or if size in bytes specified by \a param_value_size is < size of
|
|
* return type and \a param_value is not a NULL value.
|
|
* - CL_SUCCESS if the function is executed successfully.
|
|
*
|
|
*/
|
|
RUNTIME_ENTRY(cl_int, clGetThreadTraceInfoAMD, (
|
|
cl_threadtrace_amd thread_trace /* threadTrace */,
|
|
cl_threadtrace_info thread_trace_info_param,
|
|
size_t param_value_size,
|
|
void* param_value,
|
|
size_t* param_value_size_ret))
|
|
{
|
|
if (!is_valid(thread_trace)) {
|
|
return CL_INVALID_OPERATION;
|
|
}
|
|
|
|
// Find the thread trace object, associated with the specified device
|
|
const device::ThreadTrace* devThreadTrace =
|
|
as_amd(thread_trace)->getDeviceThreadTrace();
|
|
|
|
const size_t seNum = as_amd(thread_trace)->deviceSeNumThreadTrace();
|
|
switch (thread_trace_info_param) {
|
|
case CL_THREAD_TRACE_SE:
|
|
{
|
|
return amd::clGetInfo(seNum,
|
|
param_value_size, param_value, param_value_size_ret);
|
|
break;
|
|
}
|
|
case CL_THREAD_TRACE_BUFFERS_SIZE:
|
|
{
|
|
// Make sure we found a valid thread trace object
|
|
if (devThreadTrace == NULL) {
|
|
return CL_INVALID_OPERATION;
|
|
}
|
|
unsigned int bufSize2Se[2] = {0};
|
|
|
|
if (!devThreadTrace->info(thread_trace_info_param,bufSize2Se,seNum)) {
|
|
return CL_INVALID_VALUE;
|
|
}
|
|
return amd::clGetInfo(bufSize2Se,
|
|
param_value_size, param_value, param_value_size_ret);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return CL_SUCCESS;
|
|
}
|
|
RUNTIME_EXIT
|
|
|
|
/* \brief Enqueues the command for the specified thread trace object.
|
|
*
|
|
* \param command_queue must be a valid OpenCL command queue.
|
|
*
|
|
* \param thread_trace specifies the cl_threadtrace_amd object.
|
|
*
|
|
* \param event_wait_list specify [is a pointer to] events that need to
|
|
* complete before this particular command can be executed.
|
|
* If \a event_wait_list is NULL, then this particular command does not wait
|
|
* on any event to complete. If \a event_wait_list is NULL,
|
|
* \a num_events_in_wait_list must be 0. If \a event_wait_list is not NULL,
|
|
* the list of events pointed to by \a event_wait_list must be valid and
|
|
* \a num_events_in_wait_list must be greater than 0. The events specified in
|
|
* \a event_wait_list act as synchronization points.
|
|
*
|
|
* \param num_events_in_wait_list specify the number of events in
|
|
* \a event_wait_list. It must be 0 if \a event_wait_list is NULL. It must be
|
|
* greater than 0 if \a event_wait_list is not NULL.
|
|
*
|
|
* \param event returns an event object that identifies this particular
|
|
* command and can be used to query or queue a wait for this particular
|
|
* command to complete. \a event can be NULL in which case it will not be
|
|
* possible for the application to query the status of this command or queue a
|
|
* wait for this command to complete.
|
|
* \return A non zero value if OpenCL failed to release threadTrace
|
|
* - CL_INVALID_COMMAND_QUEUE if command_queue is not a valid command-queue.
|
|
* - CL_INVALID_CONTEXT if the context associated with command_queue and events in event_wait_list are not the same.
|
|
* - CL_INVALID_VALUE if the thread_trace is invalid thread trace object .
|
|
* - CL_INVALID_VALUE if the invalid command name enum value , not described in the cl_threadtrace_command_name_amd, is used.
|
|
* - CL_INVALID_OPERATION if the command enqueue failed. It can happen in the following cases:
|
|
* o BEGIN_COMMAND is queued for thread trace object for which memory object/s was/were not bound..
|
|
* o END_COMMAND is queued for thread trace object, for which BEGIN_COMMAND was not queued.
|
|
* o PAUSE_COMMAND is queued for thread trace object, for which BEGIN_COMMAND was not queued.
|
|
* o RESUME_COMMAND is queued for thread trace object, for which PAUSE_COMMAND was not queued.
|
|
* - 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.
|
|
*/
|
|
|
|
RUNTIME_ENTRY(cl_int, clEnqueueThreadTraceCommandAMD ,(
|
|
cl_command_queue command_queue ,
|
|
cl_threadtrace_amd thread_trace ,
|
|
cl_threadtrace_command_name_amd command_name ,
|
|
cl_uint num_events_in_wait_list ,
|
|
const cl_event* event_wait_list ,
|
|
cl_event* event ))
|
|
{
|
|
// Check if command queue is valid
|
|
if (!is_valid(command_queue)) {
|
|
return CL_INVALID_COMMAND_QUEUE;
|
|
}
|
|
|
|
// Check if thread trace is valid
|
|
if (!is_valid(thread_trace)) {
|
|
return CL_INVALID_OPERATION;
|
|
}
|
|
|
|
amd::ThreadTrace* amdThreadTrace = as_amd(thread_trace);
|
|
amd::HostQueue* hostQueue = as_amd(command_queue)->asHostQueue();
|
|
if (NULL == hostQueue) {
|
|
return CL_INVALID_COMMAND_QUEUE;
|
|
}
|
|
|
|
// Check that device associated with the command queue is the same as with thread trace
|
|
if (&hostQueue->device() != &amdThreadTrace->device()) {
|
|
return CL_INVALID_DEVICE;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
// Create a new command for the threadTraces
|
|
amd::ThreadTraceCommand* command = NULL;
|
|
switch (command_name) {
|
|
case CL_THREAD_TRACE_BEGIN_COMMAND :
|
|
if ((amdThreadTrace->getState() != amd::ThreadTrace::MemoryBound)
|
|
&&(amdThreadTrace->getState() != amd::ThreadTrace::End)) {
|
|
return CL_INVALID_OPERATION;
|
|
}
|
|
amdThreadTrace->setState(amd::ThreadTrace::Begin);
|
|
command = new amd::ThreadTraceCommand(*hostQueue, eventWaitList,static_cast<const void*>(&amdThreadTrace->threadTraceConfig()),
|
|
*amdThreadTrace,amd::ThreadTraceCommand::Begin,CL_COMMAND_THREAD_TRACE);
|
|
break;
|
|
case CL_THREAD_TRACE_END_COMMAND :
|
|
if ((amdThreadTrace->getState() != amd::ThreadTrace::Begin)
|
|
&&(amdThreadTrace->getState() != amd::ThreadTrace::Pause)) {
|
|
return CL_INVALID_OPERATION;
|
|
}
|
|
amdThreadTrace->setState(amd::ThreadTrace::End);
|
|
command = new amd::ThreadTraceCommand(*hostQueue, eventWaitList,&amdThreadTrace->threadTraceConfig(),
|
|
*amdThreadTrace,amd::ThreadTraceCommand::End,CL_COMMAND_THREAD_TRACE);
|
|
break;
|
|
case CL_THREAD_TRACE_PAUSE_COMMAND :
|
|
if (amdThreadTrace->getState() != amd::ThreadTrace::Begin) {
|
|
return CL_INVALID_OPERATION;
|
|
}
|
|
amdThreadTrace->setState(amd::ThreadTrace::Pause);
|
|
command = new amd::ThreadTraceCommand(*hostQueue, eventWaitList,&amdThreadTrace->threadTraceConfig(),
|
|
*amdThreadTrace,amd::ThreadTraceCommand::Pause,CL_COMMAND_THREAD_TRACE);
|
|
break;
|
|
case CL_THREAD_TRACE_RESUME_COMMAND :
|
|
if (amdThreadTrace->getState() != amd::ThreadTrace::Pause) {
|
|
return CL_INVALID_OPERATION;
|
|
}
|
|
amdThreadTrace->setState(amd::ThreadTrace::Begin);
|
|
command = new amd::ThreadTraceCommand(*hostQueue, eventWaitList,&amdThreadTrace->threadTraceConfig(),
|
|
*amdThreadTrace,amd::ThreadTraceCommand::Resume,CL_COMMAND_THREAD_TRACE);
|
|
break;
|
|
}
|
|
|
|
if (command == NULL) {
|
|
return CL_OUT_OF_HOST_MEMORY;
|
|
}
|
|
|
|
// Submit the command to the device
|
|
command->enqueue();
|
|
|
|
*not_null(event) = as_cl(&command->event());
|
|
if (event == NULL) {
|
|
command->release();
|
|
}
|
|
|
|
return CL_SUCCESS;
|
|
}
|
|
RUNTIME_EXIT
|
|
|
|
//
|
|
///*! \brief Enqueues the binding command to bind cl_threadtrace_amd to cl_mem object for trace recording..
|
|
// *
|
|
// * \param command_queue must be a valid OpenCL command queue.
|
|
// *
|
|
// * \param thread_trace specifies the cl_threadtrace_amd object.
|
|
// *
|
|
// * \param mem_objects the cl_mem objects for trace recording
|
|
// *
|
|
// * \param mem_objects_num the number of cl_mem objects in the mem_objects
|
|
// *
|
|
// * \param buffer_size the size of each cl_mem object from mem_objects
|
|
// *
|
|
// * \param event_wait_list specify [is a pointer to] events that need to
|
|
// * complete before this particular command can be executed.
|
|
// * If \a event_wait_list is NULL, then this particular command does not wait
|
|
// * on any event to complete. If \a event_wait_list is NULL,
|
|
// * \a num_events_in_wait_list must be 0. If \a event_wait_list is not NULL,
|
|
// * the list of events pointed to by \a event_wait_list must be valid and
|
|
// * \a num_events_in_wait_list must be greater than 0. The events specified in
|
|
// * \a event_wait_list act as synchronization points.
|
|
// *
|
|
// * \param num_events_in_wait_list specify the number of events in
|
|
// * \a event_wait_list. It must be 0 if \a event_wait_list is NULL. It must be
|
|
// * greater than 0 if \a event_wait_list is not NULL.
|
|
// *
|
|
// * \param event returns an event object that identifies this particular
|
|
// * command and can be used to query or queue a wait for this particular
|
|
// * command to complete. \a event can be NULL in which case it will not be
|
|
// * possible for the application to query the status of this command or queue a
|
|
// * wait for this command to complete.
|
|
// * \return A non zero value if OpenCL failed to set threadTrace buffer parameter
|
|
// * - CL_INVALID_COMMAND_QUEUE if command_queue is not a valid command-queue.
|
|
// * - CL_INVALID_CONTEXT if the context associated with command_queue and events in event_wait_list are not the same.
|
|
// * - CL_INVALID_VALUE if the thread_trace is invalid thread trace object.
|
|
// * - CL_INVALID_VALUE if the buffer_size is negative or zero.
|
|
// * - CL_INVALID_VALUE if the sub_buffers_num I less than 1.
|
|
// * - CL_INVALID_OPERATION if the mem_objects_num is not equal to the number of Shader Engines of the [GPU] device.
|
|
// * - CL_INVALID_MEM_OBJECT if one on memory objects in the mem_objects array is not a valid memory object or memory_objects is NULL.
|
|
// * - CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate memory for the data store associated from the memory objects of the mem_objects array.
|
|
// * - 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.
|
|
// */
|
|
RUNTIME_ENTRY(cl_int,clEnqueueBindThreadTraceBufferAMD ,(cl_command_queue command_queue ,
|
|
cl_threadtrace_amd thread_trace ,
|
|
cl_mem* mem_objects ,
|
|
cl_uint mem_objects_num ,
|
|
cl_uint buffer_size ,
|
|
cl_uint num_events_in_wait_list ,
|
|
const cl_event* event_wait_list ,
|
|
cl_event* event ))
|
|
{
|
|
// Check if command queue is valid
|
|
if (!is_valid(command_queue)) {
|
|
return CL_INVALID_COMMAND_QUEUE;
|
|
}
|
|
|
|
// Check if thread trace is valid
|
|
if (!is_valid(thread_trace)) {
|
|
return CL_INVALID_OPERATION;
|
|
}
|
|
|
|
// Check if input values are valid
|
|
if ((mem_objects == NULL)
|
|
|| (buffer_size <= 0)) {
|
|
return CL_INVALID_VALUE;
|
|
}
|
|
|
|
amd::ThreadTrace* amdThreadTrace = as_amd(thread_trace);
|
|
|
|
// Check if the number of bound memory objects is the same as the number of SEs
|
|
if (amdThreadTrace->deviceSeNumThreadTrace() != mem_objects_num) {
|
|
return CL_INVALID_OPERATION;
|
|
}
|
|
// Check if memory objects ,bound the thread trace,are valid
|
|
for (size_t i = 0; i < mem_objects_num; ++i) {
|
|
cl_mem obj = mem_objects[i];
|
|
if (!is_valid(obj)) {
|
|
return CL_INVALID_MEM_OBJECT;
|
|
}
|
|
}
|
|
|
|
amd::HostQueue* hostQueue = as_amd(command_queue)->asHostQueue();
|
|
if (NULL == hostQueue) {
|
|
return CL_INVALID_COMMAND_QUEUE;
|
|
}
|
|
|
|
// Check that device associated with the command queue is the same as with thread trace
|
|
if (&hostQueue->device() != &amdThreadTrace->device()) {
|
|
return CL_INVALID_DEVICE;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
amdThreadTrace->setState(amd::ThreadTrace::MemoryBound);
|
|
// Create a new ThreadTraceMemObjectsCommand command
|
|
amd::ThreadTraceMemObjectsCommand* command =
|
|
new amd::ThreadTraceMemObjectsCommand(*hostQueue, eventWaitList, mem_objects_num,mem_objects,buffer_size,*amdThreadTrace,CL_COMMAND_THREAD_TRACE_MEM);
|
|
if (command == NULL) {
|
|
return CL_OUT_OF_HOST_MEMORY;
|
|
}
|
|
|
|
// Make sure we have memory for the command execution
|
|
if (!command->validateMemory()) {
|
|
delete command;
|
|
return CL_OUT_OF_RESOURCES;
|
|
}
|
|
// Submit the command to the device
|
|
command->enqueue();
|
|
|
|
*not_null(event) = as_cl(&command->event());
|
|
if (event == NULL) {
|
|
command->release();
|
|
}
|
|
return CL_SUCCESS;
|
|
}
|
|
RUNTIME_EXIT
|
|
|
|
/*! @}
|
|
* @}
|
|
*/
|