more hacking

This commit is contained in:
Brad Hefta-Gaub 2017-02-15 09:29:45 -08:00
parent 67e6d654d9
commit 4f655bba3f
7 changed files with 93 additions and 62 deletions

View file

@ -434,8 +434,16 @@ void Agent::executeScript() {
connect(&_avatarAudioTimerThread, &QThread::finished, audioTimerWorker, &QObject::deleteLater); connect(&_avatarAudioTimerThread, &QThread::finished, audioTimerWorker, &QObject::deleteLater);
_avatarAudioTimerThread.start(); _avatarAudioTimerThread.start();
// 60Hz timer for avatar // Agents should run at 45hz
QObject::connect(_scriptEngine.get(), &ScriptEngine::update, this, &Agent::processAgentAvatar); static const int AVATAR_DATA_HZ = 45;
static const int AVATAR_DATA_IN_MSECS = MSECS_PER_SECOND / AVATAR_DATA_HZ;
QTimer* avatarDataTimer = new QTimer(this);
connect(avatarDataTimer, &QTimer::timeout, this, &Agent::processAgentAvatar);
avatarDataTimer->setSingleShot(false);
avatarDataTimer->setInterval(AVATAR_DATA_IN_MSECS);
avatarDataTimer->setTimerType(Qt::PreciseTimer);
avatarDataTimer->start();
_scriptEngine->run(); _scriptEngine->run();
Frame::clearFrameHandler(AUDIO_FRAME_TYPE); Frame::clearFrameHandler(AUDIO_FRAME_TYPE);

View file

@ -44,8 +44,9 @@ AvatarMixer::AvatarMixer(ReceivedMessage& message) :
connect(DependencyManager::get<NodeList>().data(), &NodeList::nodeKilled, this, &AvatarMixer::nodeKilled); connect(DependencyManager::get<NodeList>().data(), &NodeList::nodeKilled, this, &AvatarMixer::nodeKilled);
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver(); auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
packetReceiver.registerListener(PacketType::AvatarData, this, "queueIncomingPacket");
packetReceiver.registerListener(PacketType::ViewFrustum, this, "handleViewFrustumPacket"); packetReceiver.registerListener(PacketType::ViewFrustum, this, "handleViewFrustumPacket");
packetReceiver.registerListener(PacketType::AvatarData, this, "handleAvatarDataPacket");
packetReceiver.registerListener(PacketType::AvatarIdentity, this, "handleAvatarIdentityPacket"); packetReceiver.registerListener(PacketType::AvatarIdentity, this, "handleAvatarIdentityPacket");
packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket"); packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket");
packetReceiver.registerListener(PacketType::NodeIgnoreRequest, this, "handleNodeIgnoreRequestPacket"); packetReceiver.registerListener(PacketType::NodeIgnoreRequest, this, "handleNodeIgnoreRequestPacket");
@ -56,6 +57,14 @@ AvatarMixer::AvatarMixer(ReceivedMessage& message) :
connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &AvatarMixer::handlePacketVersionMismatch); connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &AvatarMixer::handlePacketVersionMismatch);
} }
void AvatarMixer::queueIncomingPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer node) {
auto start = usecTimestampNow();
getOrCreateClientData(node)->queuePacket(message, node);
auto end = usecTimestampNow();
_queueIncomingPacketElapsedTime += (end - start);
}
AvatarMixer::~AvatarMixer() { AvatarMixer::~AvatarMixer() {
if (_broadcastTimer) { if (_broadcastTimer) {
_broadcastTimer->deleteLater(); _broadcastTimer->deleteLater();
@ -87,8 +96,11 @@ void AvatarMixer::sendIdentityPacket(AvatarMixerClientData* nodeData, const Shar
#include <thread> #include <thread>
void AvatarMixer::start() { void AvatarMixer::start() {
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
//_slavePool.setNumThreads(1); // grins
while (!_isFinished) { while (!_isFinished) {
_loopRate.increment(); _loopRate.increment();
@ -99,34 +111,21 @@ void AvatarMixer::start() {
// Allow nodes to process any pending/queued packets across our worker threads // Allow nodes to process any pending/queued packets across our worker threads
{ {
auto start = usecTimestampNow(); auto start = usecTimestampNow();
auto nodeList = DependencyManager::get<NodeList>();
/**
nodeList->eachNode([](const SharedNodePointer& node) {
auto nodeData = dynamic_cast<AvatarMixerClientData*>(node->getLinkedData());
if (nodeData) {
nodeData->processQueuedAvatarDataPackets();
}
});
**/
nodeList->nestedEach([&](NodeList::const_iterator cbegin, NodeList::const_iterator cend) { nodeList->nestedEach([&](NodeList::const_iterator cbegin, NodeList::const_iterator cend) {
// mix across slave threads _slavePool.processIncomingPackets(cbegin, cend);
{
_slavePool.processIncomingPackets(cbegin, cend);
}
}); });
auto end = usecTimestampNow(); auto end = usecTimestampNow();
_processQueuedAvatarDataPacketsElapsedTime += (end - start); _processQueuedAvatarDataPacketsElapsedTime += (end - start);
} }
// play nice with qt event-looping // play nice with qt event-looping
{ {
// since we're a while loop we need to yield to qt's event processing // since we're a while loop we need to yield to qt's event processing
auto start = usecTimestampNow(); auto start = usecTimestampNow();
QCoreApplication::processEvents(); QCoreApplication::processEvents();
if (_isFinished) { if (_isFinished) {
// alert qt eventing that this is finished // alert qt eventing that this is finished
QCoreApplication::sendPostedEvents(this, QEvent::DeferredDelete); QCoreApplication::sendPostedEvents(this, QEvent::DeferredDelete);
@ -654,8 +653,7 @@ void AvatarMixer::nodeKilled(SharedNodePointer killedNode) {
void AvatarMixer::handleViewFrustumPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) { void AvatarMixer::handleViewFrustumPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
auto start = usecTimestampNow(); auto start = usecTimestampNow();
auto nodeList = DependencyManager::get<NodeList>(); getOrCreateClientData(senderNode);
nodeList->getOrCreateLinkedData(senderNode);
if (senderNode->getLinkedData()) { if (senderNode->getLinkedData()) {
AvatarMixerClientData* nodeData = dynamic_cast<AvatarMixerClientData*>(senderNode->getLinkedData()); AvatarMixerClientData* nodeData = dynamic_cast<AvatarMixerClientData*>(senderNode->getLinkedData());
@ -671,8 +669,7 @@ void AvatarMixer::handleViewFrustumPacket(QSharedPointer<ReceivedMessage> messag
void AvatarMixer::handleRequestsDomainListDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) { void AvatarMixer::handleRequestsDomainListDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
auto start = usecTimestampNow(); auto start = usecTimestampNow();
auto nodeList = DependencyManager::get<NodeList>(); getOrCreateClientData(senderNode);
nodeList->getOrCreateLinkedData(senderNode);
if (senderNode->getLinkedData()) { if (senderNode->getLinkedData()) {
AvatarMixerClientData* nodeData = dynamic_cast<AvatarMixerClientData*>(senderNode->getLinkedData()); AvatarMixerClientData* nodeData = dynamic_cast<AvatarMixerClientData*>(senderNode->getLinkedData());
@ -686,25 +683,10 @@ void AvatarMixer::handleRequestsDomainListDataPacket(QSharedPointer<ReceivedMess
_handleRequestsDomainListDataPacketElapsedTime += (end - start); _handleRequestsDomainListDataPacketElapsedTime += (end - start);
} }
void AvatarMixer::handleAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
auto start = usecTimestampNow();
auto nodeList = DependencyManager::get<NodeList>();
AvatarMixerClientData* nodeData = dynamic_cast<AvatarMixerClientData*>(nodeList->getOrCreateLinkedData(senderNode));
if (nodeData) {
QMutexLocker linkedDataLocker(&nodeData->getMutex()); // NOTE: we might be able to safely assume this doesn't need to be locked!
nodeData->queueAvatarDataPacket(message);
}
auto end = usecTimestampNow();
_handleAvatarDataPacketElapsedTime += (end - start);
}
void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) { void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
auto start = usecTimestampNow(); auto start = usecTimestampNow();
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
nodeList->getOrCreateLinkedData(senderNode); getOrCreateClientData(senderNode);
if (senderNode->getLinkedData()) { if (senderNode->getLinkedData()) {
AvatarMixerClientData* nodeData = dynamic_cast<AvatarMixerClientData*>(senderNode->getLinkedData()); AvatarMixerClientData* nodeData = dynamic_cast<AvatarMixerClientData*>(senderNode->getLinkedData());
@ -777,6 +759,8 @@ void AvatarMixer::sendStatsPacket() {
statsObject["timing_average_y_processEvents"] = (float)_processEventsElapsedTime / (float)_numStatFrames; statsObject["timing_average_y_processEvents"] = (float)_processEventsElapsedTime / (float)_numStatFrames;
statsObject["timing_average_y_queueIncomingPacket"] = (float)_queueIncomingPacketElapsedTime / (float)_numStatFrames;
statsObject["timing_average_z_handleAvatarDataPacket"] = (float)_handleAvatarDataPacketElapsedTime / (float)_numStatFrames; statsObject["timing_average_z_handleAvatarDataPacket"] = (float)_handleAvatarDataPacketElapsedTime / (float)_numStatFrames;
statsObject["timing_average_z_handleAvatarIdentityPacket"] = (float)_handleAvatarIdentityPacketElapsedTime / (float)_numStatFrames; statsObject["timing_average_z_handleAvatarIdentityPacket"] = (float)_handleAvatarIdentityPacketElapsedTime / (float)_numStatFrames;
@ -799,6 +783,7 @@ void AvatarMixer::sendStatsPacket() {
_handleRadiusIgnoreRequestPacketElapsedTime = 0; _handleRadiusIgnoreRequestPacketElapsedTime = 0;
_handleRequestsDomainListDataPacketElapsedTime = 0; _handleRequestsDomainListDataPacketElapsedTime = 0;
_processEventsElapsedTime = 0; _processEventsElapsedTime = 0;
_queueIncomingPacketElapsedTime = 0;
_processQueuedAvatarDataPacketsElapsedTime = 0; _processQueuedAvatarDataPacketsElapsedTime = 0;
QJsonObject avatarsObject; QJsonObject avatarsObject;
@ -875,23 +860,25 @@ void AvatarMixer::run() {
start(); start();
} }
AvatarMixerClientData* AvatarMixer::getOrCreateClientData(SharedNodePointer node) {
auto clientData = dynamic_cast<AvatarMixerClientData*>(node->getLinkedData());
if (!clientData) {
node->setLinkedData(std::unique_ptr<NodeData> { new AvatarMixerClientData(node->getUUID()) });
clientData = dynamic_cast<AvatarMixerClientData*>(node->getLinkedData());
clientData->getAvatar().setDomainMinimumScale(_domainMinimumScale);
clientData->getAvatar().setDomainMaximumScale(_domainMaximumScale);
}
return clientData;
}
void AvatarMixer::domainSettingsRequestComplete() { void AvatarMixer::domainSettingsRequestComplete() {
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::Agent, NodeType::EntityScriptServer }); nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::Agent, NodeType::EntityScriptServer });
// parse the settings to pull out the values we need // parse the settings to pull out the values we need
parseDomainServerSettings(nodeList->getDomainHandler().getSettingsObject()); parseDomainServerSettings(nodeList->getDomainHandler().getSettingsObject());
float domainMinimumScale = _domainMinimumScale;
float domainMaximumScale = _domainMaximumScale;
nodeList->linkedDataCreateCallback = [domainMinimumScale, domainMaximumScale] (Node* node) {
auto clientData = std::unique_ptr<AvatarMixerClientData> { new AvatarMixerClientData(node->getUUID()) };
clientData->getAvatar().setDomainMinimumScale(domainMinimumScale);
clientData->getAvatar().setDomainMaximumScale(domainMaximumScale);
node->setLinkedData(std::move(clientData));
};
// start the broadcastThread // start the broadcastThread
_broadcastThread.start(); _broadcastThread.start();

View file

@ -40,8 +40,9 @@ public slots:
void sendStatsPacket() override; void sendStatsPacket() override;
private slots: private slots:
void queueIncomingPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer node);
void handleViewFrustumPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode); void handleViewFrustumPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
void handleAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode); //void handleAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
void handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode); void handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
void handleKillAvatarPacket(QSharedPointer<ReceivedMessage> message); void handleKillAvatarPacket(QSharedPointer<ReceivedMessage> message);
void handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode); void handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
@ -53,6 +54,8 @@ private slots:
private: private:
AvatarMixerClientData* getOrCreateClientData(SharedNodePointer node);
void broadcastAvatarData(); void broadcastAvatarData();
void parseDomainServerSettings(const QJsonObject& domainSettings); void parseDomainServerSettings(const QJsonObject& domainSettings);
void sendIdentityPacket(AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode); void sendIdentityPacket(AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode);
@ -97,6 +100,7 @@ private:
quint64 _processEventsElapsedTime { 0 }; quint64 _processEventsElapsedTime { 0 };
quint64 _sendStatsElapsedTime { 0 }; quint64 _sendStatsElapsedTime { 0 };
quint64 _queueIncomingPacketElapsedTime { 0 };
RateCounter<> _loopRate; // this is the rate that the main thread tight loop runs RateCounter<> _loopRate; // this is the rate that the main thread tight loop runs

View file

@ -16,13 +16,43 @@
#include "AvatarMixerClientData.h" #include "AvatarMixerClientData.h"
void AvatarMixerClientData::processQueuedAvatarDataPackets() {
for (auto message : _queuedAvatarDataPackets) {
parseData(*message); void AvatarMixerClientData::queuePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer node) {
if (!_packetQueue.node) {
_packetQueue.node = node;
} }
_queuedAvatarDataPackets.clear(); _packetQueue.push(message);
} }
//
// packetReceiver.registerListener(PacketType::ViewFrustum, this, "handleViewFrustumPacket");
// packetReceiver.registerListener(PacketType::AvatarData, this, "handleAvatarDataPacket");
// packetReceiver.registerListener(PacketType::AvatarIdentity, this, "handleAvatarIdentityPacket");
// packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket");
// packetReceiver.registerListener(PacketType::NodeIgnoreRequest, this, "handleNodeIgnoreRequestPacket");
// packetReceiver.registerListener(PacketType::RadiusIgnoreRequest, this, "handleRadiusIgnoreRequestPacket");
// packetReceiver.registerListener(PacketType::RequestsDomainListData, this, "handleRequestsDomainListDataPacket");
void AvatarMixerClientData::processPackets() {
SharedNodePointer node = _packetQueue.node;
assert(_packetQueue.empty() || node);
_packetQueue.node.clear();
while (!_packetQueue.empty()) {
auto& packet = _packetQueue.back();
switch (packet->getType()) {
case PacketType::AvatarData:
parseData(*packet);
break;
default:
Q_UNREACHABLE();
}
_packetQueue.pop();
}
assert(_packetQueue.empty());
}
int AvatarMixerClientData::parseData(ReceivedMessage& message) { int AvatarMixerClientData::parseData(ReceivedMessage& message) {
// pull the sequence number from the data first // pull the sequence number from the data first

View file

@ -16,6 +16,7 @@
#include <cfloat> #include <cfloat>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include <queue>
#include <QtCore/QJsonObject> #include <QtCore/QJsonObject>
#include <QtCore/QUrl> #include <QtCore/QUrl>
@ -118,11 +119,14 @@ public:
return _lastOtherAvatarSentJoints[otherAvatar]; return _lastOtherAvatarSentJoints[otherAvatar];
} }
void queueAvatarDataPacket(QSharedPointer<ReceivedMessage> message) { _queuedAvatarDataPackets.push_back(message); } void queuePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer node);
void processQueuedAvatarDataPackets(); void processPackets();
private: private:
std::vector<QSharedPointer<ReceivedMessage>> _queuedAvatarDataPackets; struct PacketQueue : public std::queue<QSharedPointer<ReceivedMessage>> {
QWeakPointer<Node> node;
};
PacketQueue _packetQueue;
AvatarSharedPointer _avatar { new AvatarData() }; AvatarSharedPointer _avatar { new AvatarData() };

View file

@ -38,7 +38,7 @@ void AvatarMixerSlave::configure(ConstIter begin, ConstIter end) {
void AvatarMixerSlave::processIncomingPackets(const SharedNodePointer& node) { void AvatarMixerSlave::processIncomingPackets(const SharedNodePointer& node) {
auto nodeData = dynamic_cast<AvatarMixerClientData*>(node->getLinkedData()); auto nodeData = dynamic_cast<AvatarMixerClientData*>(node->getLinkedData());
if (nodeData) { if (nodeData) {
nodeData->processQueuedAvatarDataPackets(); nodeData->processPackets();
} }
} }

View file

@ -92,8 +92,6 @@ private:
// frame state // frame state
Queue _queue; Queue _queue;
unsigned int _frame { 0 };
float _throttlingRatio { 0.0f };
ConstIter _begin; ConstIter _begin;
ConstIter _end; ConstIter _end;
}; };