Merge pull request #2956 from ZappoMan/perfstats

Fix Ray Intersection bug that was causing low FPS... also added more performance debugging
This commit is contained in:
AndrewMeadows 2014-05-29 18:48:38 -07:00
commit eed2cd28ef
6 changed files with 122 additions and 55 deletions

View file

@ -2001,8 +2001,14 @@ void Application::update(float deltaTime) {
_joystickManager.update(); _joystickManager.update();
_prioVR.update(deltaTime); _prioVR.update(deltaTime);
} }
updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
{
PerformanceTimer perfTimer("idle/update/updateMyAvatar");
updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
}
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process... updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
{ {
PerformanceTimer perfTimer("idle/update/_avatarManager"); PerformanceTimer perfTimer("idle/update/_avatarManager");
_avatarManager.updateOtherAvatars(deltaTime); //loop through all the other avatars and simulate them... _avatarManager.updateOtherAvatars(deltaTime); //loop through all the other avatars and simulate them...
@ -2039,17 +2045,22 @@ void Application::update(float deltaTime) {
} }
void Application::updateMyAvatar(float deltaTime) { void Application::updateMyAvatar(float deltaTime) {
PerformanceTimer perfTimer("idle/update/updateMyAvatar"); PerformanceTimer perfTimer("updateMyAvatar");
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::updateMyAvatar()"); PerformanceWarning warn(showWarnings, "Application::updateMyAvatar()");
_myAvatar->update(deltaTime); {
PerformanceTimer perfTimer("updateMyAvatar/_myAvatar->update()");
_myAvatar->update(deltaTime);
}
// send head/hand data to the avatar mixer and voxel server {
QByteArray packet = byteArrayWithPopulatedHeader(PacketTypeAvatarData); // send head/hand data to the avatar mixer and voxel server
packet.append(_myAvatar->toByteArray()); PerformanceTimer perfTimer("updateMyAvatar/sendToAvatarMixer");
QByteArray packet = byteArrayWithPopulatedHeader(PacketTypeAvatarData);
controlledBroadcastToNodes(packet, NodeSet() << NodeType::AvatarMixer); packet.append(_myAvatar->toByteArray());
controlledBroadcastToNodes(packet, NodeSet() << NodeType::AvatarMixer);
}
// Update _viewFrustum with latest camera and view frustum data... // Update _viewFrustum with latest camera and view frustum data...
// NOTE: we get this from the view frustum, to make it simpler, since the // NOTE: we get this from the view frustum, to make it simpler, since the
@ -2057,22 +2068,28 @@ void Application::updateMyAvatar(float deltaTime) {
// We could optimize this to not actually load the viewFrustum, since we don't // We could optimize this to not actually load the viewFrustum, since we don't
// actually need to calculate the view frustum planes to send these details // actually need to calculate the view frustum planes to send these details
// to the server. // to the server.
loadViewFrustum(_myCamera, _viewFrustum); {
PerformanceTimer perfTimer("updateMyAvatar/loadViewFrustum");
loadViewFrustum(_myCamera, _viewFrustum);
}
// Update my voxel servers with my current voxel query... // Update my voxel servers with my current voxel query...
quint64 now = usecTimestampNow(); {
quint64 sinceLastQuery = now - _lastQueriedTime; PerformanceTimer perfTimer("updateMyAvatar/queryOctree");
const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND; quint64 now = usecTimestampNow();
bool queryIsDue = sinceLastQuery > TOO_LONG_SINCE_LAST_QUERY; quint64 sinceLastQuery = now - _lastQueriedTime;
bool viewIsDifferentEnough = !_lastQueriedViewFrustum.isVerySimilar(_viewFrustum); const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND;
bool queryIsDue = sinceLastQuery > TOO_LONG_SINCE_LAST_QUERY;
bool viewIsDifferentEnough = !_lastQueriedViewFrustum.isVerySimilar(_viewFrustum);
// if it's been a while since our last query or the view has significantly changed then send a query, otherwise suppress it // if it's been a while since our last query or the view has significantly changed then send a query, otherwise suppress it
if (queryIsDue || viewIsDifferentEnough) { if (queryIsDue || viewIsDifferentEnough) {
_lastQueriedTime = now; _lastQueriedTime = now;
queryOctree(NodeType::VoxelServer, PacketTypeVoxelQuery, _voxelServerJurisdictions); queryOctree(NodeType::VoxelServer, PacketTypeVoxelQuery, _voxelServerJurisdictions);
queryOctree(NodeType::ParticleServer, PacketTypeParticleQuery, _particleServerJurisdictions); queryOctree(NodeType::ParticleServer, PacketTypeParticleQuery, _particleServerJurisdictions);
queryOctree(NodeType::ModelServer, PacketTypeModelQuery, _modelServerJurisdictions); queryOctree(NodeType::ModelServer, PacketTypeModelQuery, _modelServerJurisdictions);
_lastQueriedViewFrustum = _viewFrustum; _lastQueriedViewFrustum = _viewFrustum;
}
} }
} }
@ -2300,7 +2317,7 @@ glm::vec3 Application::getSunDirection() {
} }
void Application::updateShadowMap() { void Application::updateShadowMap() {
PerformanceTimer perfTimer("pintGL/updateShadowMap"); PerformanceTimer perfTimer("paintGL/updateShadowMap");
QOpenGLFramebufferObject* fbo = _textureCache.getShadowFramebufferObject(); QOpenGLFramebufferObject* fbo = _textureCache.getShadowFramebufferObject();
fbo->bind(); fbo->bind();
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);

View file

@ -391,6 +391,9 @@ Menu::Menu() :
QMenu* perfTimerMenu = timingMenu->addMenu("Performance Timer"); QMenu* perfTimerMenu = timingMenu->addMenu("Performance Timer");
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::DisplayTimingDetails, 0, true); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::DisplayTimingDetails, 0, true);
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandDisplaySideTiming, 0, false); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandDisplaySideTiming, 0, false);
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandAvatarSimulateTiming, 0, false);
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandAvatarUpdateTiming, 0, false);
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandMiscAvatarTiming, 0, false);
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandIdleTiming, 0, false); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandIdleTiming, 0, false);
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandPaintGLTiming, 0, false); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandPaintGLTiming, 0, false);
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandUpdateTiming, 0, false); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandUpdateTiming, 0, false);

View file

@ -326,6 +326,9 @@ namespace MenuOption {
const QString EchoLocalAudio = "Echo Local Audio"; const QString EchoLocalAudio = "Echo Local Audio";
const QString EchoServerAudio = "Echo Server Audio"; const QString EchoServerAudio = "Echo Server Audio";
const QString Enable3DTVMode = "Enable 3DTV Mode"; const QString Enable3DTVMode = "Enable 3DTV Mode";
const QString ExpandMiscAvatarTiming = "Expand Misc MyAvatar Timing";
const QString ExpandAvatarUpdateTiming = "Expand MyAvatar update Timing";
const QString ExpandAvatarSimulateTiming = "Expand MyAvatar simulate Timing";
const QString ExpandDisplaySideTiming = "Expand Display Side Timing"; const QString ExpandDisplaySideTiming = "Expand Display Side Timing";
const QString ExpandIdleTiming = "Expand Idle Timing"; const QString ExpandIdleTiming = "Expand Idle Timing";
const QString ExpandPaintGLTiming = "Expand PaintGL Timing"; const QString ExpandPaintGLTiming = "Expand PaintGL Timing";

View file

@ -24,9 +24,9 @@
#include <GeometryUtil.h> #include <GeometryUtil.h>
#include <NodeList.h> #include <NodeList.h>
#include <PacketHeaders.h> #include <PacketHeaders.h>
#include <SharedUtil.h> #include <PerfStat.h>
#include <ShapeCollider.h> #include <ShapeCollider.h>
#include <SharedUtil.h>
#include "Application.h" #include "Application.h"
#include "Audio.h" #include "Audio.h"
@ -103,10 +103,15 @@ void MyAvatar::reset() {
} }
void MyAvatar::update(float deltaTime) { void MyAvatar::update(float deltaTime) {
PerformanceTimer perfTimer("MyAvatar::update/");
Head* head = getHead(); Head* head = getHead();
head->relaxLean(deltaTime); head->relaxLean(deltaTime);
updateFromTrackers(deltaTime); {
PerformanceTimer perfTimer("MyAvatar::update/updateFromTrackers");
updateFromTrackers(deltaTime);
}
if (Menu::getInstance()->isOptionChecked(MenuOption::MoveWithLean)) { if (Menu::getInstance()->isOptionChecked(MenuOption::MoveWithLean)) {
PerformanceTimer perfTimer("MyAvatar::update/moveWithLean");
// Faceshift drive is enabled, set the avatar drive based on the head position // Faceshift drive is enabled, set the avatar drive based on the head position
moveWithLean(); moveWithLean();
} }
@ -117,13 +122,18 @@ void MyAvatar::update(float deltaTime) {
head->setAudioAverageLoudness(audio->getAudioAverageInputLoudness()); head->setAudioAverageLoudness(audio->getAudioAverageInputLoudness());
if (_motionBehaviors & AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY) { if (_motionBehaviors & AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY) {
PerformanceTimer perfTimer("MyAvatar::update/gravityWork");
setGravity(Application::getInstance()->getEnvironment()->getGravity(getPosition())); setGravity(Application::getInstance()->getEnvironment()->getGravity(getPosition()));
} }
simulate(deltaTime); {
PerformanceTimer perfTimer("MyAvatar::update/simulate");
simulate(deltaTime);
}
} }
void MyAvatar::simulate(float deltaTime) { void MyAvatar::simulate(float deltaTime) {
PerformanceTimer perfTimer("MyAvatar::simulate");
if (_scale != _targetScale) { if (_scale != _targetScale) {
float scale = (1.0f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _targetScale; float scale = (1.0f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _targetScale;
@ -134,34 +144,56 @@ void MyAvatar::simulate(float deltaTime) {
// no extra movement of the hand here any more ... // no extra movement of the hand here any more ...
_handState = HAND_STATE_NULL; _handState = HAND_STATE_NULL;
updateOrientation(deltaTime); {
updatePosition(deltaTime); PerformanceTimer perfTimer("MyAvatar::simulate/updateOrientation");
updateOrientation(deltaTime);
// update avatar skeleton and simulate hand and head }
getHand()->collideAgainstOurself(); {
getHand()->simulate(deltaTime, true); PerformanceTimer perfTimer("MyAvatar::simulate/updatePosition");
updatePosition(deltaTime);
_skeletonModel.simulate(deltaTime);
simulateAttachments(deltaTime);
// copy out the skeleton joints from the model
_jointData.resize(_skeletonModel.getJointStateCount());
for (int i = 0; i < _jointData.size(); i++) {
JointData& data = _jointData[i];
data.valid = _skeletonModel.getJointState(i, data.rotation);
} }
Head* head = getHead(); {
glm::vec3 headPosition; PerformanceTimer perfTimer("MyAvatar::simulate/hand Collision,simulate");
if (!_skeletonModel.getHeadPosition(headPosition)) { // update avatar skeleton and simulate hand and head
headPosition = _position; getHand()->collideAgainstOurself();
getHand()->simulate(deltaTime, true);
}
{
PerformanceTimer perfTimer("MyAvatar::simulate/_skeletonModel.simulate()");
_skeletonModel.simulate(deltaTime);
}
{
PerformanceTimer perfTimer("MyAvatar::simulate/simulateAttachments");
simulateAttachments(deltaTime);
}
{
PerformanceTimer perfTimer("MyAvatar::simulate/copy joints");
// copy out the skeleton joints from the model
_jointData.resize(_skeletonModel.getJointStateCount());
for (int i = 0; i < _jointData.size(); i++) {
JointData& data = _jointData[i];
data.valid = _skeletonModel.getJointState(i, data.rotation);
}
}
{
PerformanceTimer perfTimer("MyAvatar::simulate/head Simulate");
Head* head = getHead();
glm::vec3 headPosition;
if (!_skeletonModel.getHeadPosition(headPosition)) {
headPosition = _position;
}
head->setPosition(headPosition);
head->setScale(_scale);
head->simulate(deltaTime, true);
} }
head->setPosition(headPosition);
head->setScale(_scale);
head->simulate(deltaTime, true);
// now that we're done stepping the avatar forward in time, compute new collisions // now that we're done stepping the avatar forward in time, compute new collisions
if (_collisionGroups != 0) { if (_collisionGroups != 0) {
PerformanceTimer perfTimer("MyAvatar::simulate/_collisionGroups");
Camera* myCamera = Application::getInstance()->getCamera(); Camera* myCamera = Application::getInstance()->getCamera();
float radius = getSkeletonHeight() * COLLISION_RADIUS_SCALE; float radius = getSkeletonHeight() * COLLISION_RADIUS_SCALE;
@ -171,14 +203,17 @@ void MyAvatar::simulate(float deltaTime) {
} }
updateShapePositions(); updateShapePositions();
if (_collisionGroups & COLLISION_GROUP_ENVIRONMENT) { if (_collisionGroups & COLLISION_GROUP_ENVIRONMENT) {
PerformanceTimer perfTimer("MyAvatar::simulate/updateCollisionWithEnvironment");
updateCollisionWithEnvironment(deltaTime, radius); updateCollisionWithEnvironment(deltaTime, radius);
} }
if (_collisionGroups & COLLISION_GROUP_VOXELS) { if (_collisionGroups & COLLISION_GROUP_VOXELS) {
PerformanceTimer perfTimer("MyAvatar::simulate/updateCollisionWithVoxels");
updateCollisionWithVoxels(deltaTime, radius); updateCollisionWithVoxels(deltaTime, radius);
} else { } else {
_trapDuration = 0.0f; _trapDuration = 0.0f;
} }
if (_collisionGroups & COLLISION_GROUP_AVATARS) { if (_collisionGroups & COLLISION_GROUP_AVATARS) {
PerformanceTimer perfTimer("MyAvatar::simulate/updateCollisionWithAvatars");
updateCollisionWithAvatars(deltaTime); updateCollisionWithAvatars(deltaTime);
} }
} }
@ -791,6 +826,7 @@ bool MyAvatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode rend
} }
float MyAvatar::computeDistanceToFloor(const glm::vec3& startPoint) { float MyAvatar::computeDistanceToFloor(const glm::vec3& startPoint) {
PerformanceTimer perfTimer("MyAvatar::computeDistanceToFloor()");
glm::vec3 direction = -_worldUpDirection; glm::vec3 direction = -_worldUpDirection;
OctreeElement* elementHit; // output from findRayIntersection OctreeElement* elementHit; // output from findRayIntersection
float distance = FLT_MAX; // output from findRayIntersection float distance = FLT_MAX; // output from findRayIntersection
@ -876,6 +912,7 @@ void MyAvatar::updateOrientation(float deltaTime) {
const float NEARBY_FLOOR_THRESHOLD = 5.0f; const float NEARBY_FLOOR_THRESHOLD = 5.0f;
void MyAvatar::updatePosition(float deltaTime) { void MyAvatar::updatePosition(float deltaTime) {
PerformanceTimer perfTimer("MyAvatar::updatePosition");
float keyboardInput = fabsf(_driveKeys[FWD] - _driveKeys[BACK]) + float keyboardInput = fabsf(_driveKeys[FWD] - _driveKeys[BACK]) +
fabsf(_driveKeys[RIGHT] - _driveKeys[LEFT]) + fabsf(_driveKeys[RIGHT] - _driveKeys[LEFT]) +
fabsf(_driveKeys[UP] - _driveKeys[DOWN]); fabsf(_driveKeys[UP] - _driveKeys[DOWN]);

View file

@ -173,6 +173,12 @@ bool Stats::includeTimingRecord(const QString& name) {
included = Menu::getInstance()->isOptionChecked(MenuOption::ExpandUpdateTiming); included = Menu::getInstance()->isOptionChecked(MenuOption::ExpandUpdateTiming);
} else if (name.startsWith("idle/")) { } else if (name.startsWith("idle/")) {
included = Menu::getInstance()->isOptionChecked(MenuOption::ExpandIdleTiming); included = Menu::getInstance()->isOptionChecked(MenuOption::ExpandIdleTiming);
} else if (name.startsWith("MyAvatar::simulate")) {
included = Menu::getInstance()->isOptionChecked(MenuOption::ExpandAvatarSimulateTiming);
} else if (name.startsWith("MyAvatar::update/") || name.startsWith("updateMyAvatar")) {
included = Menu::getInstance()->isOptionChecked(MenuOption::ExpandAvatarUpdateTiming);
} else if (name.startsWith("MyAvatar::")) {
included = Menu::getInstance()->isOptionChecked(MenuOption::ExpandMiscAvatarTiming);
} else if (name == "paintGL/displaySide") { } else if (name == "paintGL/displaySide") {
included = Menu::getInstance()->isOptionChecked(MenuOption::ExpandDisplaySideTiming) || included = Menu::getInstance()->isOptionChecked(MenuOption::ExpandDisplaySideTiming) ||
Menu::getInstance()->isOptionChecked(MenuOption::ExpandPaintGLTiming); Menu::getInstance()->isOptionChecked(MenuOption::ExpandPaintGLTiming);
@ -556,14 +562,14 @@ void Stats::display(
char perfLine[TIMER_OUTPUT_LINE_LENGTH]; char perfLine[TIMER_OUTPUT_LINE_LENGTH];
verticalOffset += STATS_PELS_PER_LINE; verticalOffset += STATS_PELS_PER_LINE;
drawText(horizontalOffset, verticalOffset, scale, rotation, font, drawText(horizontalOffset, verticalOffset, scale, rotation, font,
"---------------- Function --------------- --msecs- -calls--", color); "--------------------- Function -------------------- --msecs- -calls--", color);
const QMap<QString, PerformanceTimerRecord>& allRecords = PerformanceTimer::getAllTimerRecords(); const QMap<QString, PerformanceTimerRecord>& allRecords = PerformanceTimer::getAllTimerRecords();
QMapIterator<QString, PerformanceTimerRecord> i(allRecords); QMapIterator<QString, PerformanceTimerRecord> i(allRecords);
while (i.hasNext()) { while (i.hasNext()) {
i.next(); i.next();
if (includeTimingRecord(i.key())) { if (includeTimingRecord(i.key())) {
sprintf(perfLine, "%40s: %8.4f [%6llu]", qPrintable(i.key()), sprintf(perfLine, "%50s: %8.4f [%6llu]", qPrintable(i.key()),
(float)i.value().getMovingAverage() / (float)USECS_PER_MSEC, (float)i.value().getMovingAverage() / (float)USECS_PER_MSEC,
i.value().getCount()); i.value().getCount());

View file

@ -1308,11 +1308,6 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3
keepSearching = true; // assume that we will continue searching after this. keepSearching = true; // assume that we will continue searching after this.
// by default, we only allow intersections with leaves with content
if (!canRayIntersect()) {
return false; // we don't intersect with non-leaves, and we keep searching
}
AACube cube = getAACube(); AACube cube = getAACube();
float localDistance; float localDistance;
BoxFace localFace; BoxFace localFace;
@ -1323,6 +1318,11 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3
return false; // we did not intersect return false; // we did not intersect
} }
// by default, we only allow intersections with leaves with content
if (!canRayIntersect()) {
return false; // we don't intersect with non-leaves, and we keep searching
}
// we did hit this element, so calculate appropriate distances // we did hit this element, so calculate appropriate distances
localDistance *= TREE_SCALE; localDistance *= TREE_SCALE;
if (localDistance < distance) { if (localDistance < distance) {
@ -1346,6 +1346,7 @@ bool OctreeElement::findDetailedRayIntersection(const glm::vec3& origin, const g
if (intersectedObject) { if (intersectedObject) {
*intersectedObject = this; *intersectedObject = this;
} }
keepSearching = false;
return true; // we did intersect return true; // we did intersect
} }
return false; // we did not intersect return false; // we did not intersect