blob: 9367fa1297e96e08040282e3712bbe2c54375463 [file] [log] [blame]
/*
* Copyright (c) 2017, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "cm_queue.h"
#include "cm_debug.h"
#include "cm_device.h"
#include "cm_include.h"
#include "cm_mem.h"
#include "cm_timer.h"
struct CM_CREATEQUEUE_PARAM
{
CM_QUEUE_CREATE_OPTION createOption; // [in/out]
void *cmQueueHandle; // [out]
int32_t returnValue; // [out]
};
struct CM_ENQUEUE_PARAM
{
void *cmQueueHandle; // [in]
void *cmTaskHandle; // [in]
void *cmThreadSpaceHandle; // [in]
void *cmEventHandle; // [out]
uint32_t eventIndex; // [out] index of Event in m_EventArray
int32_t returnValue; // [out]
};
struct CM_ENQUEUEGROUP_PARAM
{
void *cmQueueHandle; // [in]
void *cmTaskHandle; // [in]
void *cmTGrpSpaceHandle; // [in]
void *cmEventHandle; // [out]
uint32_t eventIndex; // [out] index of Event in m_EventArray
int32_t returnValue; // [out]
};
struct CM_ENQUEUEHINTS_PARAM
{
void *cmQueueHandle; // [in]
void *cmTaskHandle; // [in]
void *cmEventHandle; // [in]
uint32_t hints; // [in]
uint32_t eventIndex; // [out] index of Event in m_EventArray
int32_t returnValue; // [out]
};
struct CM_DESTROYEVENT_PARAM
{
void *cmQueueHandle; // [in]
void *cmEventHandle; // [in]
int32_t returnValue; // [out]
};
struct CM_ENQUEUE_GPUCOPY_V2V_PARAM
{
void *cmQueueHandle; // [in]
void *cmSrcSurface2d; // [in]
void *cmDstSurface2d; // [in]
uint32_t option; // [in]
void *cmEventHandle; // [out]
uint32_t eventIndex; // [out] index of Event in m_EventArray
int32_t returnValue; // [out]
};
struct CM_ENQUEUE_GPUCOPY_L2L_PARAM
{
void *cmQueueHandle; // [in]
void *srcSysMem; // [in]
void *dstSysMem; // [in]
uint32_t copySize; // [in]
uint32_t option; // [in]
void *cmEventHandle; // [out]
uint32_t eventIndex; // [out] index of Event in m_EventArray
int32_t returnValue; // [out]
};
struct CM_ENQUEUE_2DInit_PARAM
{
void *cmQueueHandle; // [in]
void *cmSurface2d; // [in]
uint32_t initValue; // [in]
void *cmEventHandle; // [out]
uint32_t eventIndex; // [out] index of Event in m_EventArray
int32_t returnValue; // [out]
};
struct CM_ENQUEUE_VEBOX_PARAM
{
void *cmQueueHandle; // [IN]
void *cmVeboxHandle; // [IN] CmVeboxG75's handle
void *cmEventHandle; // [out] event's handle
uint32_t eventIndex; // [out] event's index in m_EventArray CMRT@UMD
int32_t returnValue; // [out] return value
};
int32_t CmQueue_RT::Create(CmDevice_RT *device, CmQueue_RT *&queue, CM_QUEUE_CREATE_OPTION queueCreateOption)
{
int32_t result = CM_SUCCESS;
queue = new(std::nothrow) CmQueue_RT(device, queueCreateOption);
if (queue)
{
result = queue->Initialize(queueCreateOption);
if (result != CM_SUCCESS)
{
CmQueue_RT::Destroy(queue);
}
}
else
{
CmAssert(0);
result = CM_OUT_OF_HOST_MEMORY;
}
return result;
}
int32_t CmQueue_RT::Destroy(CmQueue_RT *&queue)
{
CmSafeRelease(queue);
return CM_SUCCESS;
}
CmQueue_RT::CmQueue_RT(CmDevice_RT *device, CM_QUEUE_CREATE_OPTION queueCreateOption):
m_cmDev(device),
m_cmQueueHandle(nullptr),
m_queueOption(queueCreateOption) {}
CmQueue_RT::~CmQueue_RT() {}
int32_t CmQueue_RT::Initialize()
{
CM_CREATEQUEUE_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(inParam));
int32_t hr = m_cmDev->OSALExtensionExecute(CM_FN_CMDEVICE_CREATEQUEUE,
&inParam, sizeof(inParam));
CHK_FAILURE_RETURN(hr);
CHK_FAILURE_RETURN(inParam.returnValue);
m_cmQueueHandle = inParam.cmQueueHandle;
m_queueOption = inParam.createOption;
return CM_SUCCESS;
}
int32_t CmQueue_RT::Initialize(CM_QUEUE_CREATE_OPTION queueCreateOption)
{
CM_CREATEQUEUE_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(inParam));
inParam.createOption = queueCreateOption;
int32_t hr = m_cmDev->OSALExtensionExecute(CM_FN_CMDEVICE_CREATEQUEUEEX,
&inParam, sizeof(inParam));
CHK_FAILURE_RETURN(hr);
CHK_FAILURE_RETURN(inParam.returnValue);
m_cmQueueHandle = inParam.cmQueueHandle;
return CM_SUCCESS;
}
//!
//! Enqueue an task. Each task have one or more kernels running concurrently.
//! Each kernel can run in multiple threads concurrently.
//! Tasks get executed according to the order they get enqueued. The next task
//! doesn't start execute until the current task finishs.
//! When the last argument, pThreadSpace, is not nullptr, there are dependency among all threads within a task
//! Enqueue will make sure each x/y pair in the CmThreadSpace object is associated with
//! a unique thread in the task to enqueue.Otherwise enqueue will fail.
//! This is a non-blocking call. i.e. it returs immediately without waiting for
//! GPU to finish the execution of the task.
//! A CmEvent is generated each time a task is enqueued. The CmEvent can
//! be used to check if the task finishs.
//! INPUT:
//! 1) Array of CmKernel_RT pointers. These kernels are to run concurrently. The
//! first nullptr pointer in the array indicates the end of kernels
//! 2) Reference to the pointer to CMEvent
//! 3) A boolean value to indicate if or not to flush the queue after enqueue the task
//! by default the boolean value is TRUE.
//! OUTPUT:
//! CM_SUCCESS if the task is successfully enqueued and the CmEvent is generated;
//! CM_OUT_OF_HOST_MEMORY if out of host memery;
//! CM_FAILURE otherwise.
//! More error code is coming.
//!
CM_RT_API int32_t CmQueue_RT::Enqueue(CmTask *task,
CmEvent *&event,
const CmThreadSpace *threadSpace)
{
INSERT_PROFILER_RECORD();
if (task == nullptr)
{
CmAssert(0);
CmDebugMessage(("Kernel array is NULL."));
return CM_INVALID_ARG_VALUE;
}
m_criticalSection.Acquire();
CM_ENQUEUE_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(inParam));
inParam.cmTaskHandle = task;
inParam.cmQueueHandle = m_cmQueueHandle;
inParam.cmThreadSpaceHandle = (void *)threadSpace;
inParam.cmEventHandle = event; // to support invisiable event, this field is used for input/output.
int32_t hr = m_cmDev->OSALExtensionExecute(CM_FN_CMQUEUE_ENQUEUE,
&inParam, sizeof(inParam));
if (FAILED(hr))
{
CmAssert(0);
m_criticalSection.Release();
return hr;
}
if (inParam.returnValue != CM_SUCCESS)
{
m_criticalSection.Release();
return inParam.returnValue;
}
event = static_cast<CmEvent *>(inParam.cmEventHandle);
m_criticalSection.Release();
return CM_SUCCESS;
}
CM_RT_API int32_t CmQueue_RT::EnqueueWithHints(CmTask *task,
CmEvent *&event,
uint32_t hints)
{
INSERT_PROFILER_RECORD();
if (task == nullptr)
{
CmAssert(0);
CmDebugMessage(("Kernel array is NULL."));
return CM_INVALID_ARG_VALUE;
}
m_criticalSection.Acquire();
CM_ENQUEUEHINTS_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(inParam));
inParam.cmTaskHandle = task;
inParam.cmQueueHandle = m_cmQueueHandle;
inParam.hints = hints;
inParam.cmEventHandle = event; // to support invisable event, this field is used for input/output
int32_t hr =
m_cmDev->OSALExtensionExecute(CM_FN_CMQUEUE_ENQUEUEWITHHINTS,
&inParam, sizeof(inParam));
if (FAILED(hr))
{
CmAssert(0);
m_criticalSection.Release();
return hr;
}
if (inParam.returnValue != CM_SUCCESS)
{
m_criticalSection.Release();
return inParam.returnValue;
}
event = static_cast<CmEvent *>(inParam.cmEventHandle);
m_criticalSection.Release();
return CM_SUCCESS;
}
//!
//! Enqueue an task, which contains one pre-defined kernel to
//! copy from host memory to surface
//! This is a non-blocking call. i.e. it returs immediately without waiting for
//! GPU to finish the execution of the task.
//! A CmEvent is generated each time a task is enqueued. The CmEvent can
//! be used to check if the task finishs.
//! INPUT:
//! 1) Pointer to the CmSurface2D_RT as copy destination
//! 2) Pointer to the host memory as copy source
//! 3) Reference to the pointer to CMEvent
//! 4) A boolean value to indicate if or not to flush the queue after enqueue the task
//! by default the boolean value is TRUE.
//! OUTPUT:
//! CM_SUCCESS if the task is successfully enqueued and the CmEvent is generated;
//! CM_OUT_OF_HOST_MEMORY if out of host memery;
//! CM_FAILURE otherwise.
//! More error code is coming.
//!
int32_t CmQueue_RT::EnqueueCopyCPUToGPU(CmSurface2D *surface,
const unsigned char *sysMem,
CmEvent *&event)
{
INSERT_PROFILER_RECORD();
return EnqueueCopy(surface,
sysMem,
0,
0,
CM_FASTCOPY_CPU2GPU,
CM_FASTCOPY_OPTION_NONBLOCKING,
event);
}
//!
//! Enqueue an task, which contains one pre-defined kernel to
//! copy from surface to host memory
//! This is a non-blocking call. i.e. it returs immediately without waiting for
//! GPU to finish the execution of the task.
//! A CmEvent is generated each time a task is enqueued. The CmEvent can
//! be used to check if the task finishs.
//! INPUT:
//! 1) Pointer to the CmSurface2D_RT as copy source
//! 2) Pointer to the host memory as copy destination
//! 3) Reference to the pointer to CMEvent
//! 4) A boolean value to indicate if or not to flush the queue after enqueue the task
//! by default the boolean value is TRUE.
//! OUTPUT:
//! CM_SUCCESS if the task is successfully enqueued and the CmEvent is generated;
//! CM_OUT_OF_HOST_MEMORY if out of host memery;
//! CM_FAILURE otherwise.
//! More error code is coming.
//!
CM_RT_API int32_t CmQueue_RT::EnqueueCopyGPUToCPU(CmSurface2D *surface,
unsigned char *sysMem,
CmEvent *&event)
{
INSERT_PROFILER_RECORD();
return EnqueueCopy(surface,
sysMem,
0,
0,
CM_FASTCOPY_GPU2CPU,
CM_FASTCOPY_OPTION_NONBLOCKING,
event);
}
//!
//! Enqueue an task, which contains one pre-defined kernel to
//! copy from linear system memory to tiled video memory
//! This API supports both blocking/non-blocking copy, if user pass CM_GPUCOPY_OPTION_BLOCKING as option,
//! this API only return till copy operation is done. otherwise, this API will return immediately no waiting for copy in GPU.
//! A CmEvent is generated each time a task is enqueued. The CmEvent can
//! be used to check if the task finishs.
//! INPUT:
//! 1) Pointer to the CmSurface2D as copy destination
//! 2) Pointer to the host memory as copy resource
//! 3) width stride in bytes for system memory
//! 4) height stride in rows for system memory
//! 5) option: CM_FASTCOPY_OPTION_NONBLOCKING,CM_FASTCOPY_OPTION_BLOCKING or CM_FASTCOPY_OPTION_DISABLE_TURBO_BOOST
//! 6) Reference to the pointer to CMEvent
//!
//! RETURNS:
//! CM_SUCCESS if the task is successfully enqueued and the CmEvent is generated;
//! CM_OUT_OF_HOST_MEMORY if out of host memery;
//! CM_FAILURE otherwise.
//!
CM_RT_API int32_t
CmQueue_RT::EnqueueCopyCPUToGPUFullStride(CmSurface2D *surface,
const unsigned char *sysMem,
const uint32_t widthStride,
const uint32_t heightStride,
const uint32_t option,
CmEvent *&event)
{
INSERT_PROFILER_RECORD();
return EnqueueCopy(surface,
sysMem,
widthStride,
heightStride,
CM_FASTCOPY_CPU2GPU,
option,
event);
}
//!
//! Enqueue an task, which contains one pre-defined kernel to
//! copy from tiled video memory to linear system memory
//! This API supports both blocking/non-blocking copy, if user pass CM_FASTCOPY_OPTION_BLOCKING as option,
//! this API only return till copy operation is done. otherwise, this API will return immediately no waiting for copy in GPU.
//! A CmEvent is generated each time a task is enqueued. The CmEvent can
//! be used to check if the task finishs.
//! INPUT:
//! 1) Pointer to the CmSurface2D as copy resource
//! 2) Pointer to the host memory as copy destination
//! 3) width stride in bytes for system memory
//! 4) height stride in rows for system memory
//! 5) option: CM_FASTCOPY_OPTION_NONBLOCKING or CM_FASTCOPY_OPTION_BLOCKING
//! 6) Reference to the pointer to CMEvent
//!
//! RETURNS:
//! CM_SUCCESS if the task is successfully enqueued and the CmEvent is generated;
//! CM_OUT_OF_HOST_MEMORY if out of host memery;
//! CM_FAILURE otherwise.
//!
CM_RT_API int32_t CmQueue_RT::EnqueueCopyGPUToCPUFullStride(CmSurface2D *surface,
unsigned char *sysMem,
const uint32_t widthStride,
const uint32_t heightStride,
const uint32_t option,
CmEvent *&event)
{
INSERT_PROFILER_RECORD();
return EnqueueCopy(surface,
sysMem,
widthStride,
heightStride,
CM_FASTCOPY_GPU2CPU,
option,
event);
}
//!
//! Enqueue an task, which contains one pre-defined kernel to
//! copy from linear system memory to tiled video memory
//! This API supports both blocking/non-blocking copy, if user pass CM_GPUCOPY_OPTION_BLOCKING as option,
//! this API only return till copy operation is done. otherwise, this API will return immediately no waiting for copy in GPU.
//! A CmEvent is generated each time a task is enqueued. The CmEvent can
//! be used to check if the task finishs.
//! INPUT:
//! 1) Pointer to the CmSurface2D as copy destination
//! 2) Pointer to the host memory as copy resource
//! 3) width stride in bytes for system memory
//! 4) height stride in rows for system memory
//! 5) option: CM_FASTCOPY_OPTION_NONBLOCKING,CM_FASTCOPY_OPTION_BLOCKING or CM_FASTCOPY_OPTION_DISABLE_TURBO_BOOST
//! 6) Reference to the pointer to CMEvent
//!
//! RETURNS:
//! CM_SUCCESS if the task is successfully enqueued and the CmEvent is generated;
//! CM_OUT_OF_HOST_MEMORY if out of host memery;
//! CM_FAILURE otherwise.
//!
CM_RT_API int32_t
CmQueue_RT::EnqueueCopyCPUToGPUFullStrideDup(CmSurface2D *surface,
const unsigned char *sysMem,
const uint32_t widthStride,
const uint32_t heightStride,
const uint32_t option,
CmEvent *&event)
{
INSERT_PROFILER_RECORD();
return EnqueueCopy(surface,
sysMem,
widthStride,
heightStride,
CM_FASTCOPY_CPU2GPU,
option,
event);
}
//!
//! Enqueue an task, which contains one pre-defined kernel to
//! copy from tiled video memory to linear system memory
//! This API supports both blocking/non-blocking copy, if user pass CM_FASTCOPY_OPTION_BLOCKING as option,
//! this API only return till copy operation is done. otherwise, this API will return immediately no waiting for copy in GPU.
//! A CmEvent is generated each time a task is enqueued. The CmEvent can
//! be used to check if the task finishs.
//! INPUT:
//! 1) Pointer to the CmSurface2D as copy resource
//! 2) Pointer to the host memory as copy destination
//! 3) width stride in bytes for system memory
//! 4) height stride in rows for system memory
//! 5) option: CM_FASTCOPY_OPTION_NONBLOCKING or CM_FASTCOPY_OPTION_BLOCKING
//! 6) Reference to the pointer to CMEvent
//!
//! RETURNS:
//! CM_SUCCESS if the task is successfully enqueued and the CmEvent is generated;
//! CM_OUT_OF_HOST_MEMORY if out of host memery;
//! CM_FAILURE otherwise.
//!
CM_RT_API int32_t CmQueue_RT::EnqueueCopyGPUToCPUFullStrideDup(CmSurface2D *surface,
unsigned char *sysMem,
const uint32_t widthStride,
const uint32_t heightStride,
const uint32_t option,
CmEvent *&event)
{
INSERT_PROFILER_RECORD();
return EnqueueCopy(surface,
sysMem,
widthStride,
heightStride,
CM_FASTCOPY_GPU2CPU,
option,
event);
}
CM_RT_API int32_t CmQueue_RT::DestroyEvent(CmEvent *&event)
{
INSERT_PROFILER_RECORD();
if (event == nullptr)
{
return CM_FAILURE;
}
CM_DESTROYEVENT_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(inParam));
inParam.cmQueueHandle = m_cmQueueHandle;
inParam.cmEventHandle = event;
int32_t hr = m_cmDev->OSALExtensionExecute(CM_FN_CMQUEUE_DESTROYEVENT,
&inParam, sizeof(inParam));
CHK_FAILURE_RETURN(hr);
CHK_FAILURE_RETURN(inParam.returnValue);
event = nullptr;
return CM_SUCCESS;
}
//!
//! Function to enqueue task with thread group space pointer
//! Arguments:
//! 1. Pointer to CmTask, which can only contain one kernel.
//! 2. Reference to the pointer to CmEvent that is to be returned
//! 3. Pointer to a CmThreadGroupSpace.
//! Return Value:
//! CM_SUCCESS if the task is successfully enqueued and the CmEvent is generated
//! CM_OUT_OF_HOST_MEMORY if out of host memory
//! CM_FAILURE otherwise
//! Notes:
//! If the kernel has per thread arg, GPGPU object is to be used.
//! If the kernel has no per thread arg. GPGPU walker is used.
CM_RT_API int32_t
CmQueue_RT::EnqueueWithGroup(CmTask *task,
CmEvent *&event,
const CmThreadGroupSpace *threadGroupSpace)
{
INSERT_PROFILER_RECORD();
if (task == nullptr)
{
CmAssert(0);
CmDebugMessage(("Kernel array is NULL."));
return CM_INVALID_ARG_VALUE;
}
m_criticalSection.Acquire();
CM_ENQUEUEGROUP_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(inParam));
inParam.cmTaskHandle = task;
inParam.cmQueueHandle = m_cmQueueHandle;
inParam.cmTGrpSpaceHandle = (void *)threadGroupSpace;
inParam.cmEventHandle = event; // to support invisiable event, this field is used for input/output.
int32_t hr =
m_cmDev->OSALExtensionExecute(CM_FN_CMQUEUE_ENQUEUEWITHGROUP,
&inParam, sizeof(inParam));
if (FAILED(hr))
{
CmAssert(0);
m_criticalSection.Release();
return hr;
}
if (inParam.returnValue != CM_SUCCESS)
{
m_criticalSection.Release();
return inParam.returnValue;
}
event = static_cast<CmEvent *>(inParam.cmEventHandle);
m_criticalSection.Release();
return CM_SUCCESS;
}
int32_t CmQueue_RT::EnqueueCopy(CmSurface2D *surface,
const unsigned char *sysMem,
const uint32_t widthStride,
const uint32_t heightStride,
CM_FASTCOPY_DIRECTION direction,
const uint32_t option,
CmEvent *&event)
{
CM_ENQUEUE_GPUCOPY_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(inParam));
inParam.cmQueueHandle = m_cmQueueHandle;
inParam.cmSurface2d = surface;
inParam.sysMem = (void *)sysMem;
inParam.copyDir = direction;
inParam.widthStride = widthStride;
inParam.heightStride = heightStride;
inParam.option = option;
inParam.cmEventHandle = event;
m_criticalSection.Acquire();
int32_t hr = m_cmDev->OSALExtensionExecute(CM_FN_CMQUEUE_ENQUEUECOPY,
&inParam, sizeof(inParam),
nullptr, 0);
if (FAILED(hr))
{
CmAssert(0);
m_criticalSection.Release();
return hr;
}
if (inParam.returnValue != CM_SUCCESS)
{
m_criticalSection.Release();
return inParam.returnValue;
}
event = static_cast<CmEvent *>(inParam.cmEventHandle);
m_criticalSection.Release();
return hr;
}
CM_RT_API int32_t CmQueue_RT::EnqueueInitSurface2D(CmSurface2D *surface,
const uint32_t initValue,
CmEvent *&event)
{
INSERT_PROFILER_RECORD();
CM_ENQUEUE_2DInit_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(inParam));
inParam.cmQueueHandle = m_cmQueueHandle;
inParam.cmEventHandle = event;
inParam.cmSurface2d = surface;
inParam.initValue = initValue;
m_criticalSection.Acquire();
int32_t hr = m_cmDev->OSALExtensionExecute(CM_FN_CMQUEUE_ENQUEUESURF2DINIT,
&inParam, sizeof(inParam));
if (FAILED(hr))
{
CmAssert(0);
m_criticalSection.Release();
return hr;
}
if (inParam.returnValue != CM_SUCCESS)
{
m_criticalSection.Release();
return inParam.returnValue;
}
event = static_cast<CmEvent *>(inParam.cmEventHandle);
m_criticalSection.Release();
return hr;
}
CM_RT_API int32_t CmQueue_RT::EnqueueCopyGPUToGPU(CmSurface2D *outputSurface,
CmSurface2D *inputSurface,
uint32_t option,
CmEvent *&event)
{
INSERT_PROFILER_RECORD();
CM_ENQUEUE_GPUCOPY_V2V_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(inParam));
inParam.cmQueueHandle = m_cmQueueHandle;
inParam.option = option;
inParam.cmEventHandle = event;
inParam.cmDstSurface2d = outputSurface;
inParam.cmSrcSurface2d = inputSurface;
m_criticalSection.Acquire();
int32_t hr = m_cmDev->OSALExtensionExecute(CM_FN_CMQUEUE_ENQUEUECOPY_V2V,
&inParam, sizeof(inParam));
if (FAILED(hr))
{
CmAssert(0);
m_criticalSection.Release();
return hr;
}
if (inParam.returnValue != CM_SUCCESS)
{
m_criticalSection.Release();
return inParam.returnValue;
}
event = static_cast<CmEvent *>(inParam.cmEventHandle);
m_criticalSection.Release();
return hr;
}
CM_RT_API int32_t CmQueue_RT::EnqueueCopyCPUToCPU(unsigned char *dstSysMem,
unsigned char *srcSysMem,
uint32_t size,
uint32_t option,
CmEvent *&event)
{
INSERT_PROFILER_RECORD();
CM_ENQUEUE_GPUCOPY_L2L_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(inParam));
inParam.cmQueueHandle = m_cmQueueHandle;
inParam.srcSysMem = srcSysMem;
inParam.dstSysMem = dstSysMem;
inParam.copySize = size;
inParam.option = option;
inParam.cmEventHandle = event;
m_criticalSection.Acquire();
int32_t hr = m_cmDev->OSALExtensionExecute(CM_FN_CMQUEUE_ENQUEUECOPY_L2L,
&inParam, sizeof(inParam));
if (FAILED(hr))
{
CmAssert(0);
m_criticalSection.Release();
return hr;
}
if (inParam.returnValue != CM_SUCCESS)
{
m_criticalSection.Release();
return inParam.returnValue;
}
event = static_cast<CmEvent *>(inParam.cmEventHandle);
m_criticalSection.Release();
return hr;
}
CM_RT_API int32_t CmQueue_RT::EnqueueVebox(CmVebox *vebox, CmEvent *&event)
{
INSERT_PROFILER_RECORD();
CM_ENQUEUE_VEBOX_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(inParam));
inParam.cmQueueHandle = m_cmQueueHandle;
inParam.cmVeboxHandle = vebox;
inParam.cmEventHandle = event;
m_criticalSection.Acquire();
int32_t hr = m_cmDev->OSALExtensionExecute(CM_FN_CMQUEUE_ENQUEUEVEBOX,
&inParam, sizeof(inParam));
if (FAILED(hr))
{
CmAssert(0);
m_criticalSection.Release();
return hr;
}
if (inParam.returnValue != CM_SUCCESS)
{
m_criticalSection.Release();
return inParam.returnValue;
}
event = static_cast<CmEvent *>(inParam.cmEventHandle);
m_criticalSection.Release();
return hr;
}
CM_QUEUE_CREATE_OPTION CmQueue_RT::GetQueueOption()
{
return m_queueOption;
}
CM_RT_API int32_t CmQueue_RT::EnqueueFast(CmTask *task,
CmEvent *&event,
const CmThreadSpace *threadSpace)
{
INSERT_PROFILER_RECORD();
if (task == nullptr)
{
CmAssert(0);
CmDebugMessage(("Kernel array is NULL."));
return CM_INVALID_ARG_VALUE;
}
m_criticalSection.Acquire();
CM_ENQUEUE_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(inParam));
inParam.cmTaskHandle = task;
inParam.cmQueueHandle = m_cmQueueHandle;
inParam.cmThreadSpaceHandle = (void *)threadSpace;
inParam.cmEventHandle = event; // to support invisiable event, this field is used for input/output.
int32_t hr = m_cmDev->OSALExtensionExecute(CM_FN_CMQUEUE_ENQUEUEFAST,
&inParam, sizeof(inParam));
if (FAILED(hr))
{
CmAssert(0);
m_criticalSection.Release();
return hr;
}
if (inParam.returnValue != CM_SUCCESS)
{
m_criticalSection.Release();
return inParam.returnValue;
}
event = static_cast<CmEvent *>(inParam.cmEventHandle);
m_criticalSection.Release();
return CM_SUCCESS;
}
CM_RT_API int32_t CmQueue_RT::EnqueueWithGroupFast(CmTask *task,
CmEvent *&event,
const CmThreadGroupSpace *threadGroupSpace)
{
INSERT_PROFILER_RECORD();
if (task == nullptr)
{
CmAssert(0);
CmDebugMessage(("Kernel array is NULL."));
return CM_INVALID_ARG_VALUE;
}
m_criticalSection.Acquire();
CM_ENQUEUEGROUP_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(inParam));
inParam.cmTaskHandle = task;
inParam.cmQueueHandle = m_cmQueueHandle;
inParam.cmTGrpSpaceHandle = (void *)threadGroupSpace;
inParam.cmEventHandle = event; // to support invisiable event, this field is used for input/output.
int32_t hr =
m_cmDev->OSALExtensionExecute(CM_FN_CMQUEUE_ENQUEUEWITHGROUPFAST,
&inParam, sizeof(inParam));
if (FAILED(hr))
{
CmAssert(0);
m_criticalSection.Release();
return hr;
}
if (inParam.returnValue != CM_SUCCESS)
{
m_criticalSection.Release();
return inParam.returnValue;
}
event = static_cast<CmEvent *>(inParam.cmEventHandle);
m_criticalSection.Release();
return CM_SUCCESS;
}
CM_RT_API int32_t CmQueue_RT::DestroyEventFast(CmEvent *&event)
{
INSERT_PROFILER_RECORD();
if (event == nullptr)
{
return CM_INVALID_ARG_VALUE;
}
CM_DESTROYEVENT_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(inParam));
inParam.cmQueueHandle = m_cmQueueHandle;
inParam.cmEventHandle = event;
int32_t hr = m_cmDev->OSALExtensionExecute(CM_FN_CMQUEUE_DESTROYEVENTFAST,
&inParam, sizeof(inParam));
CHK_FAILURE_RETURN(hr);
CHK_FAILURE_RETURN(inParam.returnValue);
event = nullptr;
return CM_SUCCESS;
}
CM_RT_API int32_t CmQueue_RT::SetResidentGroupAndParallelThreadNum(uint32_t residentGroupNum, uint32_t parallelThreadNum)
{
return CM_NOT_IMPLEMENTED;
}