return result;
}
// Return ptr to node in global LL containing mem, or NULL if not found
+// Calls to this function should be wrapped in mutex
static GLOBAL_MEM_OBJ_NODE* getGlobalMemNode(const XGL_GPU_MEMORY mem)
{
GLOBAL_MEM_OBJ_NODE* pTrav = pGlobalMemObjHead;
}
// Clear the CB Binding for mem
+// Calls to this function should be wrapped in mutex
static void clearCBBinding(const XGL_CMD_BUFFER cb, const XGL_GPU_MEMORY mem)
{
GLOBAL_MEM_OBJ_NODE* pTrav = getGlobalMemNode(mem);
- MINI_NODE* pMiniCB = pTrav->pCmdBufferBindings;
- MINI_NODE* pPrev = pMiniCB;
- while (pMiniCB && (cb != pMiniCB->cmdBuffer)) {
- pPrev = pMiniCB;
- pMiniCB = pMiniCB->pNext;
- }
- if (!pMiniCB) {
- char str[1024];
- sprintf(str, "Trying to clear CB binding but CB %p not in binding list for mem obj %p", cb, mem);
- layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, cb, 0, MEMTRACK_INTERNAL_ERROR, "MEM", str);
- }
- else { // remove node from list & decrement refCount
- pPrev->pNext = pMiniCB->pNext;
- if (pMiniCB == pTrav->pCmdBufferBindings)
- pTrav->pCmdBufferBindings = NULL;
- free(pMiniCB);
- pTrav->refCount--;
+ // TODO : Having this check is not ideal, really if mem node was deleted,
+ // its CB bindings should be cleared and then freeCBBindings wouldn't call
+ // us here with stale mem objs
+ if (pTrav) {
+ MINI_NODE* pMiniCB = pTrav->pCmdBufferBindings;
+ MINI_NODE* pPrev = pMiniCB;
+ while (pMiniCB && (cb != pMiniCB->cmdBuffer)) {
+ pPrev = pMiniCB;
+ pMiniCB = pMiniCB->pNext;
+ }
+ if (!pMiniCB) {
+ char str[1024];
+ sprintf(str, "Trying to clear CB binding but CB %p not in binding list for mem obj %p", cb, mem);
+ layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, cb, 0, MEMTRACK_INTERNAL_ERROR, "MEM", str);
+ } else { // remove node from list & decrement refCount
+ pPrev->pNext = pMiniCB->pNext;
+ if (pMiniCB == pTrav->pCmdBufferBindings)
+ pTrav->pCmdBufferBindings = NULL;
+ free(pMiniCB);
+ pTrav->refCount--;
+ }
}
}
} else {
if ((pCBTrav->fence != NULL) && (pCBTrav->localFlag == XGL_TRUE)) {
nextTable.DestroyObject(pCBTrav->fence);
- pCBTrav->fence = NULL;
pCBTrav->localFlag = XGL_FALSE;
}
+ pCBTrav->fence = NULL;
MINI_NODE* pMemTrav = pCBTrav->pMemObjList;
MINI_NODE* pDeleteMe = NULL;
// We traverse LL in order and free nodes as they're cleared
return result;
}
+static void clearCBFence(const XGL_FENCE fence)
+{
+ // TODO : This is slow and stupid
+ // Ultimately would like a quick fence lookup w/ all of the CBs using that fence
+ // We have to loop every CB for now b/c multiple CBs may use same fence
+ GLOBAL_CB_NODE* pCBTrav = pGlobalCBHead;
+ while (pCBTrav) {
+ if (pCBTrav->fence == fence) {
+ pCBTrav->fence = NULL;
+ }
+ pCBTrav = pCBTrav->pNextGlobalCBNode;
+ }
+}
+
static bool32_t freeMemNode(XGL_GPU_MEMORY mem)
{
bool32_t result = XGL_TRUE;
clearObjectBinding(object);
}
}
+ if (XGL_STRUCTURE_TYPE_FENCE_CREATE_INFO == pTrav->sType) {
+ clearCBFence((XGL_FENCE)object);
+ }
if (pGlobalObjectHead == pTrav) // update HEAD if needed
pGlobalObjectHead = pTrav->pNext;
// Delete the obj node from global list
return result;
}
+XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglCreateFence(XGL_DEVICE device, const XGL_FENCE_CREATE_INFO* pCreateInfo, XGL_FENCE* pFence)
+{
+ XGL_RESULT result = nextTable.CreateFence(device, pCreateInfo, pFence);
+ if (XGL_SUCCESS == result) {
+ loader_platform_thread_lock_mutex(&globalLock);
+ insertGlobalObjectNode(*pFence, pCreateInfo->sType, pCreateInfo, sizeof(XGL_FENCE_CREATE_INFO), "fence");
+ loader_platform_thread_unlock_mutex(&globalLock);
+ }
+ return result;
+}
+
+XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglGetFenceStatus(XGL_FENCE fence)
+{
+ XGL_RESULT result = nextTable.GetFenceStatus(fence);
+ if (XGL_SUCCESS == result) {
+ // TODO : Properly we should add validation to make sure app is checking fence
+ // on CB before Reset/Begin CB call is made
+ clearCBFence(fence);
+ }
+ return result;
+}
+
+XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglWaitForFences(XGL_DEVICE device, uint32_t fenceCount, const XGL_FENCE* pFences, bool32_t waitAll, uint64_t timeout)
+{
+ XGL_RESULT result = nextTable.WaitForFences(device, fenceCount, pFences, waitAll, timeout);
+ if (XGL_SUCCESS == result) {
+ // TODO : Properly we should add validation to make sure app is checking fence
+ // on CB before Reset/Begin CB call is made
+ if (waitAll) { // Clear all the fences
+ for(uint32_t i = 0; i < fenceCount; i++) {
+ clearCBFence(pFences[i]);
+ }
+ }
+ else { // Clear only completed fences
+ for(uint32_t i = 0; i < fenceCount; i++) {
+ if (XGL_SUCCESS == nextTable.GetFenceStatus(pFences[i])) {
+ clearCBFence(pFences[i]);
+ }
+ }
+ }
+ }
+ return result;
+}
+
XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglCreateEvent(XGL_DEVICE device, const XGL_EVENT_CREATE_INFO* pCreateInfo, XGL_EVENT* pEvent)
{
XGL_RESULT result = nextTable.CreateEvent(device, pCreateInfo, pEvent);
XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglBeginCommandBuffer(XGL_CMD_BUFFER cmdBuffer, const XGL_CMD_BUFFER_BEGIN_INFO* pBeginInfo)
{
- // This implicitly resets the Cmd Buffer so clear memory references
+ // This implicitly resets the Cmd Buffer so make sure any fence is done and then clear memory references
+ GLOBAL_CB_NODE* pCBTrav = getGlobalCBNode(cmdBuffer);
+ if (pCBTrav && pCBTrav->fence) {
+ bool32_t cbDone = checkCBCompleted(cmdBuffer);
+ if (XGL_FALSE == cbDone) {
+ char str[1024];
+ sprintf(str, "Calling xglBeginCommandBuffer() on active CB %p before it has completed. You must check CB flag before this call.", cmdBuffer);
+ layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, cmdBuffer, 0, MEMTRACK_RESET_CB_WHILE_IN_FLIGHT, "MEM", str);
+ }
+ }
XGL_RESULT result = nextTable.BeginCommandBuffer(cmdBuffer, pBeginInfo);
loader_platform_thread_lock_mutex(&globalLock);
freeCBBindings(cmdBuffer);
XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglResetCommandBuffer(XGL_CMD_BUFFER cmdBuffer)
{
- // Clear memory references as this point. Anything else to do here?
+ // Verify that CB is complete (not in-flight)
+ GLOBAL_CB_NODE* pCBTrav = getGlobalCBNode(cmdBuffer);
+ if (pCBTrav && pCBTrav->fence) {
+ bool32_t cbDone = checkCBCompleted(cmdBuffer);
+ if (XGL_FALSE == cbDone) {
+ char str[1024];
+ sprintf(str, "Resetting CB %p before it has completed. You must check CB flag before calling xglResetCommandBuffer().", cmdBuffer);
+ layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, cmdBuffer, 0, MEMTRACK_RESET_CB_WHILE_IN_FLIGHT, "MEM", str);
+ }
+ }
+ // Clear memory references as this point.
loader_platform_thread_lock_mutex(&globalLock);
freeCBBindings(cmdBuffer);
loader_platform_thread_unlock_mutex(&globalLock);
return (void*) xglGetObjectInfo;
if (!strcmp(funcName, "xglBindObjectMemory"))
return (void*) xglBindObjectMemory;
+ if (!strcmp(funcName, "xglCreateFence"))
+ return (void*) xglCreateFence;
+ if (!strcmp(funcName, "xglGetFenceStatus"))
+ return (void*) xglGetFenceStatus;
+ if (!strcmp(funcName, "xglWaitForFences"))
+ return (void*) xglWaitForFences;
if (!strcmp(funcName, "xglCreateEvent"))
return (void*) xglCreateEvent;
if (!strcmp(funcName, "xglCreateQueryPool"))