static XGL_LAYER_DISPATCH_TABLE nextTable;
static XGL_BASE_LAYER_OBJECT *pCurObj;
static pthread_once_t tabOnce = PTHREAD_ONCE_INIT;
+// Could be smarter about locking with unique locks for various tasks, but just using one for now
+pthread_mutex_t globalLock = PTHREAD_MUTEX_INITIALIZER;
// Ptr to LL of dbg functions
static XGL_LAYER_DBG_FUNCTION_NODE *pDbgFunctionHead = NULL;
// Utility function to handle reporting
const XGL_CHAR* pLayerPrefix,
const XGL_CHAR* pMsg)
{
+ pthread_mutex_lock(&globalLock);
XGL_LAYER_DBG_FUNCTION_NODE *pTrav = pDbgFunctionHead;
if (pTrav) {
while (pTrav) {
break;
}
}
+ pthread_mutex_unlock(&globalLock);
}
// Return the size of the underlying struct based on struct type
static XGL_SIZE sTypeStructSize(XGL_STRUCTURE_TYPE sType)
// Viewport state create info doesn't have sType so we have to pass in BIND_POINT
static void insertDynamicState(const XGL_STATE_OBJECT state, const PIPELINE_LL_HEADER* pCreateInfo, const XGL_STATE_BIND_POINT sType)
{
+ pthread_mutex_lock(&globalLock);
// Insert new node at head of appropriate LL
DYNAMIC_STATE_NODE* pStateNode = (DYNAMIC_STATE_NODE*)malloc(sizeof(DYNAMIC_STATE_NODE));
pStateNode->pNext = pDynamicStateHead[sType];
pStateNode->sType = sType;
pStateNode->pCreateInfo = (PIPELINE_LL_HEADER*)malloc(dynStateCreateInfoSize(sType));
memcpy(pStateNode->pCreateInfo, pCreateInfo, dynStateCreateInfoSize(sType));
+ pthread_mutex_unlock(&globalLock);
}
// Set the last bound dynamic state of given type
// TODO : Need to track this per cmdBuffer and correlate cmdBuffer for Draw w/ last bound for that cmdBuffer?
static void setLastBoundDynamicState(const XGL_STATE_OBJECT state, const XGL_STATE_BIND_POINT sType)
{
+ pthread_mutex_lock(&globalLock);
DYNAMIC_STATE_NODE* pTrav = pDynamicStateHead[sType];
while (pTrav && (state != pTrav->stateObj)) {
pTrav = pTrav->pNext;
layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, state, 0, DRAWSTATE_INVALID_DYNAMIC_STATE_OBJECT, "DS", str);
}
pLastBoundDynamicState[sType] = pTrav;
+ pthread_mutex_unlock(&globalLock);
}
// Print the last bound dynamic state
static void printDynamicState()
{
+ pthread_mutex_lock(&globalLock);
char str[1024];
for (uint32_t i = 0; i < XGL_NUM_STATE_BIND_POINT; i++) {
if (pLastBoundDynamicState[i]) {
layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, NULL, 0, DRAWSTATE_NONE, "DS", str);
}
}
+ pthread_mutex_unlock(&globalLock);
}
// Retrieve pipeline node ptr for given pipeline object
static PIPELINE_NODE *getPipeline(XGL_PIPELINE pipeline)
{
+ pthread_mutex_lock(&globalLock);
PIPELINE_NODE *pTrav = pPipelineHead;
while (pTrav) {
- if (pTrav->pipeline == pipeline)
+ if (pTrav->pipeline == pipeline) {
+ pthread_mutex_unlock(&globalLock);
return pTrav;
+ }
pTrav = pTrav->pNext;
}
+ pthread_mutex_unlock(&globalLock);
return NULL;
}
// For given sampler, return a ptr to its Create Info struct, or NULL if sampler not found
static XGL_SAMPLER_CREATE_INFO* getSamplerCreateInfo(const XGL_SAMPLER sampler)
{
+ pthread_mutex_lock(&globalLock);
SAMPLER_NODE *pTrav = pSamplerHead;
while (pTrav) {
- if (sampler == pTrav->sampler)
+ if (sampler == pTrav->sampler) {
+ pthread_mutex_unlock(&globalLock);
return &pTrav->createInfo;
+ }
pTrav = pTrav->pNext;
}
+ pthread_mutex_unlock(&globalLock);
return NULL;
}
// Init the pipeline mapping info based on pipeline create info LL tree
+// Threading note : Calls to this function should wrapped in mutex
static void initPipeline(PIPELINE_NODE *pPipeline, const XGL_GRAPHICS_PIPELINE_CREATE_INFO* pCreateInfo)
{
// First init create info, we'll shadow the structs as we go down the tree
// Return DS Head ptr for specified ds or else NULL
static DS_LL_HEAD* getDS(XGL_DESCRIPTOR_SET ds)
{
+ pthread_mutex_lock(&globalLock);
DS_LL_HEAD *pTrav = pDSHead;
while (pTrav) {
- if (pTrav->dsID == ds)
+ if (pTrav->dsID == ds) {
+ pthread_mutex_unlock(&globalLock);
return pTrav;
+ }
pTrav = pTrav->pNextDS;
}
+ pthread_mutex_unlock(&globalLock);
return NULL;
}
}
// Clear specified slotCount DS Slots starting at startSlot
-// Return XGL_TRUE if DS is within a xglBeginDescriptorSetUpdate() call sequence, otherwise XGL_FALSE
+// Return XGL_TRUE if DS exists and is successfully cleared to 0s
static XGL_BOOL clearDS(XGL_DESCRIPTOR_SET descriptorSet, XGL_UINT startSlot, XGL_UINT slotCount)
{
DS_LL_HEAD *pTrav = getDS(descriptorSet);
+ pthread_mutex_lock(&globalLock);
if (!pTrav || ((startSlot + slotCount) > pTrav->numSlots)) {
// TODO : Log more meaningful error here
+ pthread_mutex_unlock(&globalLock);
return XGL_FALSE;
}
for (uint32_t i = startSlot; i < slotCount; i++) {
memset((void*)&pTrav->dsSlot[i], 0, sizeof(DS_SLOT));
}
+ pthread_mutex_unlock(&globalLock);
return XGL_TRUE;
}
}
else {
// Synch Descriptor Set Mapping
+ pthread_mutex_lock(&globalLock);
for (uint32_t i = 0; i < XGL_MAX_DESCRIPTOR_SETS; i++) {
DS_LL_HEAD *pDS;
if (lastBoundDS[i]) {
free(tmpStr);
}
}
+ pthread_mutex_unlock(&globalLock);
}
}
uint32_t skipUnusedCount = 0; // track consecutive unused slots for minimal reporting
char tmp_str[1024];
char ds_config_str[1024*256] = {0}; // TODO : Currently making this buffer HUGE w/o overrun protection. Need to be smarter, start smaller, and grow as needed.
+ pthread_mutex_lock(&globalLock);
for (uint32_t i = 0; i < XGL_MAX_DESCRIPTOR_SETS; i++) {
if (lastBoundDS[i]) {
DS_LL_HEAD *pDS = getDS(lastBoundDS[i]);
}
}
}
+ pthread_mutex_unlock(&globalLock);
layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, NULL, 0, DRAWSTATE_NONE, "DS", ds_config_str);
}
char str[1024];
sprintf(str, "Created Gfx Pipeline %p", (void*)*pPipeline);
layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, pPipeline, 0, DRAWSTATE_NONE, "DS", str);
+ pthread_mutex_lock(&globalLock);
PIPELINE_NODE *pTrav = pPipelineHead;
if (pTrav) {
while (pTrav->pNext)
memset((void*)pTrav, 0, sizeof(PIPELINE_NODE));
pTrav->pipeline = *pPipeline;
initPipeline(pTrav, pCreateInfo);
+ pthread_mutex_unlock(&globalLock);
return result;
}
XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglCreateSampler(XGL_DEVICE device, const XGL_SAMPLER_CREATE_INFO* pCreateInfo, XGL_SAMPLER* pSampler)
{
XGL_RESULT result = nextTable.CreateSampler(device, pCreateInfo, pSampler);
- // TODO : Save sampler create info here and associate it with SAMPLER
+ pthread_mutex_lock(&globalLock);
SAMPLER_NODE *pNewNode = (SAMPLER_NODE*)malloc(sizeof(SAMPLER_NODE));
pNewNode->sampler = *pSampler;
memcpy(&pNewNode->createInfo, pCreateInfo, sizeof(XGL_SAMPLER_CREATE_INFO));
pNewNode->pNext = pSamplerHead;
pSamplerHead = pNewNode;
+ pthread_mutex_unlock(&globalLock);
return result;
}
char str[1024];
sprintf(str, "Created Descriptor Set (DS) %p", (void*)*pDescriptorSet);
layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, pDescriptorSet, 0, DRAWSTATE_NONE, "DS", str);
+ pthread_mutex_lock(&globalLock);
DS_LL_HEAD *pTrav = pDSHead;
if (pTrav) {
// Grow existing list
pTrav->pNextDS = NULL;
pTrav->updateActive = XGL_FALSE;
initDS(pTrav);
+ pthread_mutex_unlock(&globalLock);
return result;
}
{
if (getDS(descriptorSet)) {
assert(index < XGL_MAX_DESCRIPTOR_SETS);
+ pthread_mutex_lock(&globalLock);
lastBoundDS[index] = descriptorSet;
lastBoundSlotOffset[index] = slotOffset;
+ pthread_mutex_unlock(&globalLock);
char str[1024];
sprintf(str, "DS %p bound to DS index %u on pipeline %s", (void*)descriptorSet, index, string_XGL_PIPELINE_BIND_POINT(pipelineBindPoint));
layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, descriptorSet, 0, DRAWSTATE_NONE, "DS", str);