SWR_ASSERT(pCurDrawContext->pArena->IsEmpty() == true);
+ // Reset dependency
pCurDrawContext->dependent = false;
+ pCurDrawContext->dependentFE = false;
+
pCurDrawContext->pContext = pContext;
pCurDrawContext->isCompute = false; // Dispatch has to set this to true.
CachingArena* pArena;
uint32_t drawId;
- bool dependent;
+ bool dependentFE; // Frontend work is dependent on all previous FE
+ bool dependent; // Backend work is dependent on all previous BE
bool isCompute; // Is this DC a compute context?
bool cleanupState; // True if this is the last draw using an entry in the state ring.
volatile bool doneFE; // Is FE work done for this draw?
return pDC->dependent && IDComparesLess(lastRetiredDraw, pDC->drawId - 1);
}
+bool CheckDependencyFE(SWR_CONTEXT *pContext, DRAW_CONTEXT *pDC, uint32_t lastRetiredDraw)
+{
+ return pDC->dependentFE && IDComparesLess(lastRetiredDraw, pDC->drawId - 1);
+}
+
//////////////////////////////////////////////////////////////////////////
/// @brief Update client stats.
INLINE void UpdateClientStats(SWR_CONTEXT* pContext, uint32_t workerId, DRAW_CONTEXT* pDC)
// Ensure all streaming writes are globally visible before marking this FE done
_mm_mfence();
pDC->doneFE = true;
+
InterlockedDecrement((volatile LONG*)&pContext->drawsOutstandingFE);
}
{
uint32_t dcSlot = curDrawFE % KNOB_MAX_DRAWS_IN_FLIGHT;
DRAW_CONTEXT *pDC = &pContext->dcRing[dcSlot];
- if (pDC->isCompute || pDC->doneFE || pDC->FeLock)
+ if (pDC->isCompute || pDC->doneFE)
{
CompleteDrawContextInl(pContext, workerId, pDC);
curDrawFE++;
}
}
+ uint32_t lastRetiredFE = curDrawFE - 1;
uint32_t curDraw = curDrawFE;
while (IDComparesLess(curDraw, drawEnqueued))
{
if (!pDC->isCompute && !pDC->FeLock)
{
+ if (CheckDependencyFE(pContext, pDC, lastRetiredFE))
+ {
+ return;
+ }
+
uint32_t initial = InterlockedCompareExchange((volatile uint32_t*)&pDC->FeLock, 1, 0);
if (initial == 0)
{