diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index ae3aec3572..675a71a2f4 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -73,6 +73,7 @@ namespace render { avatarPtr->setDisplayingLookatTarget(renderLookAtTarget); if (avatarPtr->isInitialized() && args) { + PROFILE_RANGE_BATCH(*args->_batch, "renderAvatarPayload"); avatarPtr->render(args, qApp->getCamera()->getPosition()); } } @@ -334,6 +335,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { } auto& batch = *renderArgs->_batch; + PROFILE_RANGE_BATCH(batch, __FUNCTION__); if (glm::distance(DependencyManager::get()->getMyAvatar()->getPosition(), _position) < 10.0f) { auto geometryCache = DependencyManager::get(); @@ -360,6 +362,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { } if (havePosition && haveRotation) { + PROFILE_RANGE_BATCH(batch, __FUNCTION__":leftHandPointer"); Transform pointerTransform; pointerTransform.setTranslation(position); pointerTransform.setRotation(rotation); @@ -383,6 +386,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { } if (havePosition && haveRotation) { + PROFILE_RANGE_BATCH(batch, __FUNCTION__":rightHandPointer"); Transform pointerTransform; pointerTransform.setTranslation(position); pointerTransform.setRotation(rotation); @@ -455,6 +459,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { bool renderBounding = Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes); if (renderBounding && shouldRenderHead(renderArgs) && _skeletonModel.isRenderable()) { + PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes"); _skeletonModel.renderBoundingCollisionShapes(*renderArgs->_batch, 0.7f); } @@ -464,6 +469,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { static const float INDICATOR_RADIUS = 0.03f; static const glm::vec4 LOOK_AT_INDICATOR_COLOR = { 0.8f, 0.0f, 0.0f, 0.75f }; glm::vec3 position = glm::vec3(_position.x, getDisplayNamePosition().y + INDICATOR_OFFSET, _position.z); + PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderFocusIndicator"); Transform transform; transform.setTranslation(position); transform.postScale(INDICATOR_RADIUS); @@ -472,6 +478,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { // If the avatar is looking at me, indicate that they are if (getHead()->isLookingAtMe() && Menu::getInstance()->isOptionChecked(MenuOption::ShowWhosLookingAtMe)) { + PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderLookingAtMe"); const glm::vec3 LOOKING_AT_ME_COLOR = { 1.0f, 1.0f, 1.0f }; const float LOOKING_AT_ME_ALPHA_START = 0.8f; const float LOOKING_AT_ME_DURATION = 0.5f; // seconds @@ -517,6 +524,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { const float MIN_VOICE_SPHERE_DISTANCE = 12.0f; if (Menu::getInstance()->isOptionChecked(MenuOption::BlueSpeechSphere) && distanceToTarget > MIN_VOICE_SPHERE_DISTANCE) { + PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderVoiceSphere"); // render voice intensity sphere for avatars that are farther away const float MAX_SPHERE_ANGLE = 10.0f * RADIANS_PER_DEGREE; @@ -684,6 +692,7 @@ void Avatar::renderBillboard(RenderArgs* renderArgs) { glm::vec2 texCoordBottomRight(1.0f, 1.0f); gpu::Batch& batch = *renderArgs->_batch; + PROFILE_RANGE_BATCH(batch, __FUNCTION__); batch.setResourceTexture(0, _billboardTexture->getGPUTexture()); DependencyManager::get()->bindSimpleProgram(batch, true); DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, @@ -766,6 +775,8 @@ Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, cons } void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, const glm::vec3& textPosition) const { + PROFILE_RANGE_BATCH(batch, __FUNCTION__); + bool shouldShowReceiveStats = DependencyManager::get()->shouldShowReceiveStats() && !isMyAvatar(); // If we have nothing to draw, or it's totally transparent, or it's too close or behind the camera, return @@ -816,17 +827,24 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, co // Test on extent above insures abs(height) > 0.0f textTransform.postScale(1.0f / height); batch.setModelTransform(textTransform); - - DependencyManager::get()->bindSimpleProgram(batch, false, true, true, true); - DependencyManager::get()->renderBevelCornersRect(batch, left, bottom, width, height, - bevelDistance, backgroundColor); + + { + PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderBevelCornersRect"); + DependencyManager::get()->bindSimpleProgram(batch, false, true, true, true); + DependencyManager::get()->renderBevelCornersRect(batch, left, bottom, width, height, + bevelDistance, backgroundColor); + } + // Render actual name QByteArray nameUTF8 = renderedDisplayName.toLocal8Bit(); // Render text slightly in front to avoid z-fighting textTransform.postTranslate(glm::vec3(0.0f, 0.0f, SLIGHTLY_IN_FRONT * renderer->getFontSize())); batch.setModelTransform(textTransform); - renderer->draw(batch, text_x, -text_y, nameUTF8.data(), textColor); + { + PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderText"); + renderer->draw(batch, text_x, -text_y, nameUTF8.data(), textColor); + } } } @@ -1089,6 +1107,7 @@ void Avatar::renderJointConnectingCone(gpu::Batch& batch, glm::vec3 position1, g points << p1a << p1b << p2a << p1b << p2a << p2b; } + PROFILE_RANGE_BATCH(batch, __FUNCTION__); // TODO: this is really inefficient constantly recreating these vertices buffers. It would be // better if the avatars cached these buffers for each of the joints they are rendering geometryCache->updateVertices(_jointConesID, points, color); diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index c3e186a630..2e3ea7fc36 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -22,6 +22,14 @@ ProfileRange::ProfileRange(const char *name) { ProfileRange::~ProfileRange() { nvtxRangePop(); } + +ProfileRangeBatch::ProfileRangeBatch(gpu::Batch& batch, const char *name) : _batch(batch) { + _batch.pushProfileRange(name); +} + +ProfileRangeBatch::~ProfileRangeBatch() { + _batch.popProfileRange(); +} #endif #define ADD_COMMAND(call) _commands.push_back(COMMAND_##call); _commandOffsets.push_back(_params.size()); @@ -391,3 +399,17 @@ QDebug& operator<<(QDebug& debug, const Batch::CacheState& cacheState) { return debug; } + +// Debugging +void Batch::pushProfileRange(const char* name) { +#if defined(NSIGHT_FOUND) + ADD_COMMAND(pushProfileRange); + _params.push_back(_profileRanges.cache(name)); +#endif +} + +void Batch::popProfileRange() { +#if defined(NSIGHT_FOUND) + ADD_COMMAND(popProfileRange); +#endif +} diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index deb70f7a68..8397f92da6 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -229,6 +229,10 @@ public: // Reset the stage caches and states void resetStages(); + // Debugging + void pushProfileRange(const char* name); + void popProfileRange(); + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API @@ -324,6 +328,9 @@ public: COMMAND_glColor4f, + COMMAND_pushProfileRange, + COMMAND_popProfileRange, + NUM_COMMANDS, }; typedef std::vector Commands; @@ -389,6 +396,7 @@ public: typedef Cache::Vector PipelineCaches; typedef Cache::Vector FramebufferCaches; typedef Cache::Vector QueryCaches; + typedef Cache::Vector ProfileRangeCaches; typedef Cache>::Vector LambdaCache; // Cache Data in a byte array if too big to fit in Param @@ -416,6 +424,7 @@ public: FramebufferCaches _framebuffers; QueryCaches _queries; LambdaCache _lambdas; + ProfileRangeCaches _profileRanges; NamedBatchDataMap _namedData; @@ -429,6 +438,25 @@ protected: } +#if defined(NSIGHT_FOUND) + +class ProfileRangeBatch { +public: + ProfileRangeBatch(gpu::Batch& batch, const char *name); + ~ProfileRangeBatch(); + +private: + gpu::Batch& _batch; +}; + +#define PROFILE_RANGE_BATCH(batch, name) ProfileRangeBatch profileRangeThis(batch, name); + +#else + +#define PROFILE_RANGE_BATCH(batch, name) + +#endif + QDebug& operator<<(QDebug& debug, const gpu::Batch::CacheState& cacheState); #endif diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 19edbaee5f..e49a3ba6c0 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -15,6 +15,11 @@ #include #include +#if defined(NSIGHT_FOUND) +#include "nvToolsExt.h" +#endif + + using namespace gpu; GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = @@ -69,6 +74,9 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_glUniformMatrix4fv), (&::gpu::GLBackend::do_glColor4f), + + (&::gpu::GLBackend::do_pushProfileRange), + (&::gpu::GLBackend::do_popProfileRange), }; void GLBackend::init() { @@ -710,3 +718,17 @@ void GLBackend::do_glColor4f(Batch& batch, uint32 paramOffset) { } (void) CHECK_GL_ERROR(); } + + +void GLBackend::do_pushProfileRange(Batch& batch, uint32 paramOffset) { +#if defined(NSIGHT_FOUND) + auto name = batch._profileRanges.get(batch._params[paramOffset]._uint); + nvtxRangePush(name.c_str()); +#endif +} + +void GLBackend::do_popProfileRange(Batch& batch, uint32 paramOffset) { +#if defined(NSIGHT_FOUND) + nvtxRangePop(); +#endif +} diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 6c359d81f1..9f1e17205c 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -479,6 +479,9 @@ protected: void do_glColor4f(Batch& batch, uint32 paramOffset); + void do_pushProfileRange(Batch& batch, uint32 paramOffset); + void do_popProfileRange(Batch& batch, uint32 paramOffset); + typedef void (GLBackend::*CommandCall)(Batch&, uint32); static CommandCall _commandCalls[Batch::NUM_COMMANDS]; };