From 99d23b698552a2692084492f1c999987caac60f8 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Wed, 14 Jan 2015 12:47:30 -0700 Subject: layers: Updated MemTracker to track per-region memory transition states for allocations --- demos/tri.c | 7 +++++-- layers/mem_tracker.c | 53 +++++++++++++++++++++++++++++++++++++++++++--------- layers/mem_tracker.h | 8 ++++---- 3 files changed, 53 insertions(+), 15 deletions(-) diff --git a/demos/tri.c b/demos/tri.c index 0059e037..3a89bf1b 100644 --- a/demos/tri.c +++ b/demos/tri.c @@ -153,7 +153,8 @@ static void demo_draw(struct demo *demo) err = xglWaitForFences(demo->device, 1, &fence, XGL_TRUE, ~((XGL_UINT64) 0)); assert(err == XGL_SUCCESS || err == XGL_ERROR_UNAVAILABLE); - XGL_MEMORY_REF memRefs[4]; + static const uint32_t NUM_MEM_REFS = 5; + XGL_MEMORY_REF memRefs[NUM_MEM_REFS]; memRefs[0].mem = demo->depth.mem; memRefs[0].flags = 0; memRefs[1].mem = demo->textures[0].mem; @@ -162,8 +163,10 @@ static void demo_draw(struct demo *demo) memRefs[2].flags = 0; memRefs[3].mem = demo->buffers[1].mem; memRefs[3].flags = 0; + memRefs[4].mem = demo->vertices.mem; + memRefs[4].flags = 0; err = xglQueueSubmit(demo->queue, 1, &demo->cmd, - 4, memRefs, XGL_NULL_HANDLE); + NUM_MEM_REFS, memRefs, XGL_NULL_HANDLE); assert(!err); err = xglWsiX11QueuePresent(demo->queue, &present, fence); diff --git a/layers/mem_tracker.c b/layers/mem_tracker.c index 42f26b33..cd09b789 100644 --- a/layers/mem_tracker.c +++ b/layers/mem_tracker.c @@ -257,11 +257,11 @@ static void setMemTransition(const XGL_GPU_MEMORY mem, const XGL_MEMORY_STATE_TR // TODO : Flag error for missing node } else { - MEM_STATE_TRANSITION_NODE* pMTNode = pTrav->pTransitions; + MEM_STATE_TRANSITION_NODE* pMTNode = pTrav->pRegions; MEM_STATE_TRANSITION_NODE* pPrevMTNode = pMTNode; // TODO : Not sure of best way (or need) to distinguish mem from image here // Verify that it's being used as memory (not image) - //if (!pTrav->pTransitions.isMem) { + //if (!pTrav->pRegions.isMem) { // TODO : Flag error for setting mem transition on image memory //} // Basic state update algorithm @@ -280,8 +280,10 @@ static void setMemTransition(const XGL_GPU_MEMORY mem, const XGL_MEMORY_STATE_TR MEM_STATE_TRANSITION_NODE* pNewNode = (MEM_STATE_TRANSITION_NODE*)malloc(sizeof(MEM_STATE_TRANSITION_NODE)); memset(pNewNode, 0, sizeof(MEM_STATE_TRANSITION_NODE)); memcpy(&pNewNode->transition, pTransition, sizeof(XGL_MEMORY_STATE_TRANSITION)); + // Increment numRegions here and will be appropriately decremented below if needed + pTrav->numRegions++; if (!pMTNode) { // Initialization case, just set HEAD ptr to new node - pTrav->pTransitions = pNewNode; + pTrav->pRegions = pNewNode; } else { // If offset of new state is less than current offset, insert it & update state after it as needed @@ -295,14 +297,21 @@ static void setMemTransition(const XGL_GPU_MEMORY mem, const XGL_MEMORY_STATE_TR saveStartNode = 1; pMTNode->transition.memory.regionSize = pTransition->offset - pMTNode->transition.memory.offset; pMTNode->pNext = pNewNode; + // TODO: Verify that prev newState matches new oldState } else { // start point of regions are equal // Prev ptr now points to new region - if (pPrevMTNode == pTrav->pTransitions) - pTrav->pTransitions = pNewNode; + if (pPrevMTNode == pTrav->pRegions) + pTrav->pRegions = pNewNode; else pPrevMTNode->pNext = pNewNode; } + // New region is overlaying old region so make sure states match + if (pMTNode->transition.memory.newState != pNewNode->transition.memory.oldState) { + char str[1024]; + sprintf(str, "Setting Memory state transition for mem %p, current newState of %s doesn't match overlapping transition oldState of %s", mem, string_XGL_MEMORY_STATE(pMTNode->transition.memory.newState), string_XGL_MEMORY_STATE(pNewNode->transition.memory.oldState)); + layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, mem, 0, MEMTRACK_INVALID_STATE, "MEM", str); + } // Start point insertion complete, find end point XGL_GPU_SIZE newEndPoint = pTransition->offset + pTransition->regionSize; XGL_GPU_SIZE curEndPoint = pMTNode->transition.memory.offset + pMTNode->transition.memory.regionSize; @@ -316,6 +325,11 @@ static void setMemTransition(const XGL_GPU_MEMORY mem, const XGL_MEMORY_STATE_TR pMTNode = pMTNode->pNext; // TODO : Handle NULL pMTNode case curEndPoint = pMTNode->transition.memory.offset + pMTNode->transition.memory.regionSize; + if (pMTNode->transition.memory.newState != pNewNode->transition.memory.oldState) { + char str[1024]; + sprintf(str, "Setting Memory state transition for mem %p, current newState of %s doesn't match overlapping transition oldState of %s", mem, string_XGL_MEMORY_STATE(pMTNode->transition.memory.newState), string_XGL_MEMORY_STATE(pNewNode->transition.memory.oldState)); + layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, mem, 0, MEMTRACK_INVALID_STATE, "MEM", str); + } } if (newEndPoint < curEndPoint) { // split end region @@ -329,8 +343,11 @@ static void setMemTransition(const XGL_GPU_MEMORY mem, const XGL_MEMORY_STATE_TR pFreeMe = pMTNode; } // Free any regions that are no longer needed - if ((1 == saveStartNode) && (NULL != pFreeMe)) + if ((1 == saveStartNode) && (NULL != pFreeMe)) { pFreeMe = pFreeMe->pNext; + numToFree--; + } + pTrav->numRegions -= numToFree; MEM_STATE_TRANSITION_NODE* pNodeToFree; while (numToFree) { pNodeToFree = pFreeMe; @@ -369,6 +386,7 @@ static void insertGlobalMemObj(const XGL_GPU_MEMORY mem, const XGL_MEMORY_ALLOC_ if (pAllocInfo) { // TODO : How to handle Wsi-created alloc? // Create initial state node that covers entire allocation // TODO : How to handle image memory? + pTrav->numRegions = 0; // This will be updated during setMemTransition call XGL_MEMORY_STATE_TRANSITION initMemStateTrans; memset(&initMemStateTrans, 0, sizeof(XGL_MEMORY_STATE_TRANSITION)); initMemStateTrans.sType = XGL_STRUCTURE_TYPE_MEMORY_STATE_TRANSITION; @@ -538,7 +556,7 @@ static void deleteGlobalMemNode(XGL_GPU_MEMORY mem) if (pGlobalMemObjHead == pTrav) pGlobalMemObjHead = pTrav->pNextGlobalNode; // delete transition list off of this node - MEM_STATE_TRANSITION_NODE* pMSTNode = pTrav->pTransitions; + MEM_STATE_TRANSITION_NODE* pMSTNode = pTrav->pRegions; MEM_STATE_TRANSITION_NODE* pPrevMSTNode = pMSTNode; while(pMSTNode) { pPrevMSTNode = pMSTNode; @@ -744,8 +762,11 @@ static XGL_BOOL updateObjectBinding(XGL_OBJECT object, XGL_GPU_MEMORY mem) XGL_MEMORY_STATE_TRANSITION initMemStateTrans; memset(&initMemStateTrans, 0, sizeof(XGL_MEMORY_STATE_TRANSITION)); initMemStateTrans.mem = mem; - initMemStateTrans.oldState = XGL_IMAGE_STATE_UNINITIALIZED_TARGET; - initMemStateTrans.newState = XGL_IMAGE_STATE_UNINITIALIZED_TARGET; + //initMemStateTrans.oldState = XGL_IMAGE_STATE_UNINITIALIZED_TARGET; + //initMemStateTrans.newState = XGL_IMAGE_STATE_UNINITIALIZED_TARGET; + // TODO : For now just using initial memory state + initMemStateTrans.oldState = XGL_MEMORY_STATE_DATA_TRANSFER; + initMemStateTrans.newState = XGL_MEMORY_STATE_DATA_TRANSFER; initMemStateTrans.offset = 0; initMemStateTrans.regionSize = pTrav->allocInfo.allocationSize; setMemTransition(mem, &initMemStateTrans); @@ -857,6 +878,20 @@ static void printMemList() pCBTrav = pCBTrav->pNext; } } + MEM_STATE_TRANSITION_NODE* pTrans = pTrav->pRegions; + if (!pTrans) { + sprintf(str, " No regions"); + layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, NULL, 0, MEMTRACK_NONE, "MEM", str); + } + else { + sprintf(str, " XGL_MEMORY_STATE_TRANSITION (MST) regions list w/ HEAD at %p:", pTrans); + layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, NULL, 0, MEMTRACK_NONE, "MEM", str); + while (pTrans) { + sprintf(str, " MST_NODE(%p):\n%s", pTrans, xgl_print_xgl_memory_state_transition(&pTrans->transition.memory, "{MEM}INFO : ")); + layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, NULL, 0, MEMTRACK_NONE, "MEM", str); + pTrans = pTrans->pNext; + } + } pTrav = pTrav->pNextGlobalNode; } } diff --git a/layers/mem_tracker.h b/layers/mem_tracker.h index 7196b9db..61951a96 100644 --- a/layers/mem_tracker.h +++ b/layers/mem_tracker.h @@ -40,7 +40,7 @@ typedef enum _MEM_TRACK_ERROR MEMTRACK_MEMORY_BINDING_ERROR = 12, // Error during one of many calls that bind memory to object or CB MEMTRACK_OUT_OF_MEMORY_ERROR = 13, // malloc failed MEMTRACK_MEMORY_LEAK = 14, // Failure to call xglFreeMemory on Mem Obj prior to DestroyDevice - MEMTRACK_INVALID_STATE = 15, // Failure to call xglFreeMemory on Mem Obj prior to DestroyDevice + MEMTRACK_INVALID_STATE = 15, // Memory not in the correct state } MEM_TRACK_ERROR; /* @@ -94,8 +94,7 @@ struct GLOBAL_MEM_OBJ_NODE; // Store a linked-list of transition nodes to account for different states across a single mem obj typedef struct _MEM_STATE_TRANSITION_NODE { struct _MEM_STATE_TRANSITION_NODE* pNext; - uint32_t numRegions; // Allocation may be broken into various regions - uint32_t isMem; // 1 for memory, 0 for image + //uint32_t isMem; // 1 for memory, 0 for image union { XGL_MEMORY_STATE_TRANSITION memory; XGL_IMAGE_STATE_TRANSITION image; // use when img attached to this mem obj @@ -110,7 +109,8 @@ typedef struct _GLOBAL_MEM_OBJ_NODE { XGL_UINT refCount; // Count of references (obj bindings or CB use) XGL_GPU_MEMORY mem; XGL_MEMORY_ALLOC_INFO allocInfo; - MEM_STATE_TRANSITION_NODE* pTransitions; // LL of transitions for this Mem Obj + uint32_t numRegions; // Allocation may be broken into various regions + MEM_STATE_TRANSITION_NODE* pRegions; // LL of transitions for this Mem Obj } GLOBAL_MEM_OBJ_NODE; typedef struct _GLOBAL_OBJECT_NODE { -- cgit v1.2.3