initial commit
Этот коммит содержится в:
@@ -0,0 +1,202 @@
|
||||
|
||||
#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;
|
||||
m_queries[slot]->GetResult(m_cs, ¶m, waitType);
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
Ссылка в новой задаче
Block a user