2014-07-04 16:17:05 -04:00
|
|
|
|
|
|
|
|
#include "EventQueue.h"
|
|
|
|
|
#include "query/QueryObject.h"
|
|
|
|
|
#include "gsl_ctx.h"
|
|
|
|
|
|
|
|
|
|
EventQueue::EventQueue()
|
|
|
|
|
{
|
|
|
|
|
m_cs = NULL;
|
|
|
|
|
m_queueSize = c_staticQueueSize;
|
|
|
|
|
|
|
|
|
|
memset(m_queries,0,sizeof(m_queries));
|
|
|
|
|
memset(m_flushed,0,sizeof(m_flushed));
|
|
|
|
|
|
|
|
|
|
m_latestRetired = 0;
|
|
|
|
|
m_headId = m_queueSize - 1 ;
|
|
|
|
|
m_tail = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EventQueue::~EventQueue()
|
|
|
|
|
{
|
|
|
|
|
for (unsigned int i = 0; i < c_staticQueueSize; i++)
|
|
|
|
|
{
|
|
|
|
|
assert(m_queries[i] == 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
EventQueue::open(gsCtx* cs, gslQueryTarget target, EQManagerConfig config, uint32 engineMask)
|
|
|
|
|
{
|
|
|
|
|
assert((config == EQManager_HIGH) || (config == EQManager_LOW));
|
|
|
|
|
setSlotCount((int) config);
|
|
|
|
|
assert((GpuEvent::InvalidID+1) % m_queueSize == 0);
|
|
|
|
|
|
|
|
|
|
m_cs = cs;
|
|
|
|
|
|
|
|
|
|
m_headId = m_queueSize - 1 ;
|
|
|
|
|
m_tail = 0;
|
|
|
|
|
m_latestRetired = 0;
|
|
|
|
|
m_target = target;
|
|
|
|
|
m_engineMask = engineMask;
|
|
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < m_queueSize; i++)
|
|
|
|
|
{
|
|
|
|
|
m_queries[i] = cs->createQuery(target);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
EventQueue::close()
|
|
|
|
|
{
|
|
|
|
|
if (!m_cs) // the queue is unintialized.
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < m_queueSize; i++)
|
|
|
|
|
{
|
|
|
|
|
m_cs->destroyQuery(m_queries[i]);
|
|
|
|
|
}
|
|
|
|
|
memset(m_queries, 0, sizeof(m_queries));
|
|
|
|
|
memset(m_flushed, 0, sizeof(m_flushed));
|
|
|
|
|
m_latestRetired = 0;
|
|
|
|
|
m_headId = m_queueSize - 1 ;
|
|
|
|
|
m_tail = 0;
|
|
|
|
|
m_cs = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
EventQueue::begin()
|
|
|
|
|
{
|
|
|
|
|
const CALuint slot = m_headId % m_queueSize;
|
|
|
|
|
gslErrorCode ec = m_queries[slot]->BeginQuery(m_cs, m_target, 0, m_engineMask);
|
|
|
|
|
assert(ec == GSL_NO_ERROR);
|
|
|
|
|
|
|
|
|
|
m_flushed[slot] = false; // we've started a query, but it hasn't been checked yet...
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32
|
|
|
|
|
EventQueue::end()
|
|
|
|
|
{
|
|
|
|
|
uint32 ret = m_headId;
|
|
|
|
|
const uint32 slot = m_headId % m_queueSize;
|
|
|
|
|
|
|
|
|
|
m_queries[slot]->EndQuery(m_cs, 0);
|
|
|
|
|
|
|
|
|
|
m_headId++;
|
|
|
|
|
m_tail++;
|
|
|
|
|
|
|
|
|
|
if (GpuEvent::InvalidID == m_headId)
|
|
|
|
|
{
|
|
|
|
|
// Flush on an event ID wrap around or when the Queue is going to wrap in
|
|
|
|
|
flush();
|
|
|
|
|
//roll numbers back to the beginning
|
|
|
|
|
m_latestRetired = 0;
|
|
|
|
|
m_headId = m_headId % m_queueSize;
|
|
|
|
|
m_tail = m_tail % m_queueSize;
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
EventQueue::isDone(uint32 event)
|
|
|
|
|
{
|
|
|
|
|
assert((event < GpuEvent::InvalidID) && "illegal event handle");
|
|
|
|
|
// if the event is older the the last known retired event we
|
|
|
|
|
// do not need to process it.
|
|
|
|
|
if (event <= m_latestRetired)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if the event is older than the oldest event handle we have
|
|
|
|
|
// we synchronize with the oldest event.
|
|
|
|
|
if (event < m_tail)
|
|
|
|
|
{
|
|
|
|
|
return waitForEvent(m_tail, CAL_WAIT_LOW_CPU_UTILIZATION);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// If we've never called flush on the query object, go ahead flush the first time to ensure
|
|
|
|
|
// we never infinite loop
|
|
|
|
|
//
|
|
|
|
|
const uint32 slot = event % m_queueSize;
|
|
|
|
|
if (!m_flushed[slot])
|
|
|
|
|
{
|
|
|
|
|
flush();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Since we're in between, we actually have to check to see if things are truely done
|
|
|
|
|
//
|
|
|
|
|
bool retVal = m_queries[slot]->IsResultAvailable(m_cs);
|
|
|
|
|
|
|
|
|
|
// cache the most recently retired event
|
|
|
|
|
if (retVal && (event < m_headId) && (event > m_latestRetired))
|
|
|
|
|
{
|
|
|
|
|
m_latestRetired = event;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return retVal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
EventQueue::waitForEvent(uint32 event, uint32 waitType)
|
|
|
|
|
{
|
|
|
|
|
// if we already retired a younger event we don't to process current events
|
|
|
|
|
if (event <= m_latestRetired)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if the event is older than the oldest event handle we have
|
|
|
|
|
// we synchronize with the oldest event
|
|
|
|
|
if (event < m_tail)
|
|
|
|
|
{
|
|
|
|
|
event = m_tail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// If we've never called flush on the query object, go ahead flush the first time to ensure
|
|
|
|
|
// we never infinite loop
|
|
|
|
|
//
|
|
|
|
|
const uint32 slot = event % m_queueSize;
|
|
|
|
|
if (!m_flushed[slot])
|
|
|
|
|
{
|
|
|
|
|
flush();
|
|
|
|
|
}
|
|
|
|
|
uint64 param;
|
2017-01-11 11:49:32 -05:00
|
|
|
m_queries[slot]->GetResult(m_cs, ¶m, (IOSyncWaitType) waitType);
|
2014-07-04 16:17:05 -04:00
|
|
|
|
|
|
|
|
// cache the most recently retired event
|
|
|
|
|
if ((event < m_headId) && (event > m_latestRetired))
|
|
|
|
|
{
|
|
|
|
|
m_latestRetired = event;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (param != 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
EventQueue::flush()
|
|
|
|
|
{
|
|
|
|
|
m_cs->Flush(false, m_engineMask);
|
|
|
|
|
memset(m_flushed, 1, sizeof(m_flushed));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
EventQueue::setSlotCount(uint32 slotCount)
|
|
|
|
|
{
|
|
|
|
|
if (slotCount < c_staticQueueSize)
|
|
|
|
|
{
|
|
|
|
|
m_queueSize = slotCount;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_queueSize = c_staticQueueSize;
|
|
|
|
|
}
|
|
|
|
|
}
|