}
}
-//static bool32_t validateCBMemRef(const XGL_CMD_BUFFER cb, uint32_t memRefCount, const XGL_MEMORY_REF* pMemRefs)
-//{
-// bool32_t result = XGL_TRUE;
-// MT_CB_INFO* pInfo = getCBInfo(cb);
-// if (!pInfo) {
-// char str[1024];
-// sprintf(str, "Unable to find info for CB %p in order to check memory references", (void*)cb);
-// layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, cb, 0, MEMTRACK_INVALID_CB, "MEM", str);
-// result = XGL_FALSE;
-// } else {
-// // Validate that all actual references are accounted for in pMemRefs
-// uint32_t i;
-// uint8_t found = 0;
-// uint64_t foundCount = 0;
-
-// for (list<XGL_GPU_MEMORY>::iterator it = pInfo->pMemObjList.begin(); it != pInfo->pMemObjList.end(); ++it) {
-// for (i = 0; i < memRefCount; i++) {
-// if ((*it) == pMemRefs[i].mem) {
-// char str[1024];
-// sprintf(str, "Found Mem Obj %p binding to CB %p", (*it), cb);
-// layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, cb, 0, MEMTRACK_NONE, "MEM", str);
-// found = 1;
-// foundCount++;
-// break;
-// }
-// }
-// if (!found) {
-// char str[1024];
-// sprintf(str, "Memory reference list for Command Buffer %p is missing ref to mem obj %p", cb, (*it));
-// layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, cb, 0, MEMTRACK_CB_MISSING_MEM_REF, "MEM", str);
-// result = XGL_FALSE;
-// }
-// found = 0;
-// }
-
-// if (result == XGL_TRUE) {
-// char str[1024];
-// sprintf(str, "Verified all %lu memory dependencies for CB %p are included in pMemRefs list", foundCount, cb);
-// layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, cb, 0, MEMTRACK_NONE, "MEM", str);
-// // TODO : Could report mem refs in pMemRefs that AREN'T in mem list, that would be primarily informational
-// // Currently just noting that there is a difference
-// if (foundCount != memRefCount) {
-// sprintf(str, "There are %u mem refs included in pMemRefs list, but only %lu are required", memRefCount, foundCount);
-// layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, cb, 0, MEMTRACK_NONE, "MEM", str);
-// }
-// }
-// }
-// return result;
-//}
+// Returns True if a memory reference is present in a Queue's memory reference list
+// Queue is validated by caller
+static bool32_t checkMemRef(
+ XGL_QUEUE queue,
+ XGL_GPU_MEMORY mem)
+{
+ bool32_t result = XGL_FALSE;
+ list<XGL_GPU_MEMORY>::iterator it;
+ MT_QUEUE_INFO *pQueueInfo = queueMap[queue];
+ for (it = pQueueInfo->pMemRefList.begin(); it != pQueueInfo->pMemRefList.end(); ++it) {
+ if ((*it) == mem) {
+ result = XGL_TRUE;
+ break;
+ }
+ }
+ return result;
+}
+
+static bool32_t validateQueueMemRefs(
+ XGL_QUEUE queue,
+ uint32_t cmdBufferCount,
+ const XGL_CMD_BUFFER *pCmdBuffers)
+{
+ bool32_t result = XGL_TRUE;
+
+ // Verify Queue
+ MT_QUEUE_INFO *pQueueInfo = queueMap[queue];
+ if (pQueueInfo == NULL) {
+ char str[1024];
+ sprintf(str, "Unknown Queue %p specified in xglQueueSubmit", queue);
+ layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, queue, 0, MEMTRACK_INVALID_QUEUE, "MEM", str);
+ }
+ else {
+ // Iterate through all CBs in pCmdBuffers
+ for (uint32_t i = 0; i < cmdBufferCount; i++) {
+ MT_CB_INFO* pCBInfo = getCBInfo(pCmdBuffers[i]);
+ if (!pCBInfo) {
+ char str[1024];
+ sprintf(str, "Unable to find info for CB %p in order to check memory references in xglQueueSubmit for queue %p", (void*)pCmdBuffers[i], queue);
+ layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, pCmdBuffers[i], 0, MEMTRACK_INVALID_CB, "MEM", str);
+ result = XGL_FALSE;
+ } else {
+ // Validate that all actual references are accounted for in pMemRefs
+ for (list<XGL_GPU_MEMORY>::iterator it = pCBInfo->pMemObjList.begin(); it != pCBInfo->pMemObjList.end(); ++it) {
+ // Search for each memref in queues memreflist.
+ if (checkMemRef(queue, *it)) {
+ char str[1024];
+ sprintf(str, "Found Mem Obj %p binding to CB %p for queue %p", (*it), pCmdBuffers[i], queue);
+ layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, pCmdBuffers[i], 0, MEMTRACK_NONE, "MEM", str);
+ }
+ else {
+ char str[1024];
+ sprintf(str, "Queue %p Memory reference list for Command Buffer %p is missing ref to mem obj %p", queue, pCmdBuffers[i], (*it));
+ layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, pCmdBuffers[i], 0, MEMTRACK_INVALID_MEM_REF, "MEM", str);
+ result = XGL_FALSE;
+ }
+ }
+ }
+ }
+ if (result == XGL_TRUE) {
+ char str[1024];
+ sprintf(str, "Verified all memory dependencies for Queue %p are included in pMemRefs list", queue);
+ layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, queue, 0, MEMTRACK_NONE, "MEM", str);
+ // TODO : Could report mem refs in pMemRefs that AREN'T in mem list, that would be primarily informational
+ // Currently just noting that there is a difference
+ }
+ }
+
+ return result;
+}
// Return ptr to info in map container containing mem, or NULL if not found
// Calls to this function should be wrapped in mutex
// Report any memory leaks
MT_MEM_OBJ_INFO* pInfo = NULL;
for (map<XGL_GPU_MEMORY, MT_MEM_OBJ_INFO*>::iterator ii=memObjMap.begin(); ii!=memObjMap.end(); ++ii) {
- pInfo = (*ii).second;
+ pInfo = (*ii).second;
if (pInfo->allocInfo.allocationSize != 0) {
sprintf(str, "Mem Object %p has not been freed. You should clean up this memory by calling xglFreeMemory(%p) prior to xglDestroyDevice().",
XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglGetDeviceQueue(XGL_DEVICE device, uint32_t queueNodeIndex, uint32_t queueIndex, XGL_QUEUE* pQueue)
{
XGL_RESULT result = nextTable.GetDeviceQueue(device, queueNodeIndex, queueIndex, pQueue);
- addQueueInfo(*pQueue);
+ if (result == XGL_SUCCESS) {
+ loader_platform_thread_lock_mutex(&globalLock);
+ addQueueInfo(*pQueue);
+ loader_platform_thread_unlock_mutex(&globalLock);
+ }
+ return result;
+}
+
+XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglQueueAddMemReference(XGL_QUEUE queue, XGL_GPU_MEMORY mem)
+{
+ XGL_RESULT result = nextTable.QueueAddMemReference(queue, mem);
+ if (result == XGL_SUCCESS) {
+ loader_platform_thread_lock_mutex(&globalLock);
+
+ MT_QUEUE_INFO *pQueueInfo = queueMap[queue];
+ if (pQueueInfo == NULL) {
+ char str[1024];
+ sprintf(str, "Unknown Queue %p", queue);
+ layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, queue, 0, MEMTRACK_INVALID_QUEUE, "MEM", str);
+ }
+ else {
+ if (checkMemRef(queue, mem) == XGL_TRUE) {
+ // Alread in list, just warn
+ char str[1024];
+ sprintf(str, "Request to add a memory reference (%p) to Queue %p -- ref is already present in the queue's reference list", mem, queue);
+ layerCbMsg(XGL_DBG_MSG_WARNING, XGL_VALIDATION_LEVEL_0, mem, 0, MEMTRACK_INVALID_MEM_REF, "MEM", str);
+ }
+ else {
+ // Add to queue's memory reference list
+ pQueueInfo->pMemRefList.push_front(mem);
+ }
+ }
+ loader_platform_thread_unlock_mutex(&globalLock);
+ }
+ return result;
+}
+
+XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglQueueRemoveMemReference(XGL_QUEUE queue, XGL_GPU_MEMORY mem)
+{
+ // TODO : Decrement ref count for this memory reference on this queue. Remove if ref count is zero.
+ XGL_RESULT result = nextTable.QueueRemoveMemReference(queue, mem);
+ if (result == XGL_SUCCESS) {
+ loader_platform_thread_lock_mutex(&globalLock);
+
+ MT_QUEUE_INFO *pQueueInfo = queueMap[queue];
+ if (pQueueInfo == NULL) {
+ char str[1024];
+ sprintf(str, "Unknown Queue %p", queue);
+ layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, queue, 0, MEMTRACK_INVALID_QUEUE, "MEM", str);
+ }
+ else {
+ for (list<XGL_GPU_MEMORY>::iterator it = pQueueInfo->pMemRefList.begin(); it != pQueueInfo->pMemRefList.end(); ++it) {
+ if ((*it) == mem) {
+ it = pQueueInfo->pMemRefList.erase(it);
+ }
+ }
+ }
+ loader_platform_thread_unlock_mutex(&globalLock);
+ }
return result;
}
-XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglQueueSubmit(XGL_QUEUE queue, uint32_t cmdBufferCount, const XGL_CMD_BUFFER* pCmdBuffers, XGL_FENCE fence)
+XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglQueueSubmit(
+ XGL_QUEUE queue,
+ uint32_t cmdBufferCount,
+ const XGL_CMD_BUFFER *pCmdBuffers,
+ XGL_FENCE fence)
{
loader_platform_thread_lock_mutex(&globalLock);
// TODO : Need to track fence and clear mem references when fence clears
MT_CB_INFO* pCBInfo = NULL;
uint64_t fenceId = addFenceInfo(fence, queue);
- char str[1024];
- sprintf(str, "In xglQueueSubmit(), checking %u cmdBuffers memRefs", cmdBufferCount);
- layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, queue, 0, MEMTRACK_NONE, "MEM", str);
+
printMemList();
printCBList();
for (uint32_t i = 0; i < cmdBufferCount; i++) {
pCBInfo = getCBInfo(pCmdBuffers[i]);
pCBInfo->fenceId = fenceId;
- sprintf(str, "Verifying mem refs for CB %p", pCmdBuffers[i]);
- layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, pCmdBuffers[i], 0, MEMTRACK_NONE, "MEM", str);
-// if (XGL_FALSE == validateCBMemRef(pCmdBuffers[i], memRefCount, pMemRefs)) {
-// sprintf(str, "Unable to verify memory references for CB %p", (void*)pCmdBuffers[i]);
-// layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, pCmdBuffers[i], 0, MEMTRACK_CB_MISSING_MEM_REF, "MEM", str);
-// }
}
- printCBList();
+
+ if (XGL_FALSE == validateQueueMemRefs(queue, cmdBufferCount, pCmdBuffers)) {
+ char str[1024];
+ sprintf(str, "Unable to verify memory references for Queue %p", queue);
+ layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, queue, 0, MEMTRACK_INVALID_MEM_REF, "MEM", str);
+ }
+
loader_platform_thread_unlock_mutex(&globalLock);
XGL_RESULT result = nextTable.QueueSubmit(queue, cmdBufferCount, pCmdBuffers, getFenceFromId(fenceId));
return result;
return (void*) xglDbgUnregisterMsgCallback;
if (!strcmp(funcName, "xglGetDeviceQueue"))
return (void*) xglGetDeviceQueue;
+ if (!strcmp(funcName, "xglQueueAddMemReference"))
+ return (void*) xglQueueAddMemReference;
+ if (!strcmp(funcName, "xglQueueRemoveMemReference"))
+ return (void*) xglQueueRemoveMemReference;
#if !defined(WIN32)
if (!strcmp(funcName, "xglWsiX11CreatePresentableImage"))
return (void*) xglWsiX11CreatePresentableImage;
// Mem Tracker ERROR codes
typedef enum _MEM_TRACK_ERROR
{
- MEMTRACK_NONE = 0, // Used for INFO & other non-error messages
- MEMTRACK_INVALID_CB = 1, // Cmd Buffer invalid
- MEMTRACK_CB_MISSING_MEM_REF = 2, // pMemRefs for CB is missing a mem ref
- MEMTRACK_INVALID_MEM_OBJ = 3, // Invalid Memory Object
- MEMTRACK_INTERNAL_ERROR = 4, // Bug in Mem Track Layer internal data structures
- MEMTRACK_CB_MISSING_FENCE = 5, // Cmd Buffer does not have fence
- MEMTRACK_FREED_MEM_REF = 6, // MEM Obj freed while it still has obj and/or CB refs
- MEMTRACK_MEM_OBJ_CLEAR_EMPTY_BINDINGS = 7, // Clearing bindings on mem obj that doesn't have any bindings
- MEMTRACK_MISSING_MEM_BINDINGS = 8, // Trying to retrieve mem bindings, but none found (may be internal error)
- MEMTRACK_INVALID_OBJECT = 9, // Attempting to reference generic XGL Object that is invalid
+ MEMTRACK_NONE = 0, // Used for INFO & other non-error messages
+ MEMTRACK_INVALID_CB = 1, // Cmd Buffer invalid
+ MEMTRACK_INVALID_MEM_REF = 2, // Requested mem ref is missing or invalid
+ MEMTRACK_INVALID_MEM_OBJ = 3, // Invalid Memory Object
+ MEMTRACK_INTERNAL_ERROR = 4, // Bug in Mem Track Layer internal data structures
+ MEMTRACK_CB_MISSING_FENCE = 5, // Cmd Buffer does not have fence
+ MEMTRACK_FREED_MEM_REF = 6, // MEM Obj freed while it still has obj and/or CB refs
+ MEMTRACK_MEM_OBJ_CLEAR_EMPTY_BINDINGS = 7, // Clearing bindings on mem obj that doesn't have any bindings
+ MEMTRACK_MISSING_MEM_BINDINGS = 8, // Trying to retrieve mem bindings, but none found (may be internal error)
+ MEMTRACK_INVALID_OBJECT = 9, // Attempting to reference generic XGL Object that is invalid
MEMTRACK_FREE_MEM_ERROR = 10, // Error while calling xglFreeMemory
MEMTRACK_DESTROY_OBJECT_ERROR = 11, // Destroying an object that has a memory reference
MEMTRACK_MEMORY_BINDING_ERROR = 12, // Error during one of many calls that bind memory to object or CB
MEMTRACK_MEMORY_LEAK = 14, // Failure to call xglFreeMemory on Mem Obj prior to DestroyDevice
MEMTRACK_INVALID_STATE = 15, // Memory not in the correct state
MEMTRACK_RESET_CB_WHILE_IN_FLIGHT = 16, // xglResetCommandBuffer() called on a CB that hasn't completed
+ MEMTRACK_INVALID_QUEUE = 17, // Invalid queue requested or selected
} MEM_TRACK_ERROR;
/*
uint64_t lastRetiredId;
uint64_t lastSubmittedId;
list<XGL_CMD_BUFFER> pQueueCmdBuffers;
+ list<XGL_GPU_MEMORY> pMemRefList;
};
#ifdef __cplusplus