From 345733173f0ba87ba00964d8468c230af667971d Mon Sep 17 00:00:00 2001 From: Runitai Linden Date: Mon, 24 Jan 2022 14:54:52 -0600 Subject: SL-16594 Fix for occasional single-frame culling of rigged attachments --- indra/newview/llvoavatar.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index e40fdff751..13ae43c7d6 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2839,13 +2839,21 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) attached_object->mDrawable->makeActive(); attached_object->mDrawable->updateXform(TRUE); - if (!rigged) + if (bridge) { - if (bridge) + if (!rigged) { gPipeline.updateMoveNormalAsync(bridge); } + else + { + //specialized impl of updateMoveNormalAsync just for rigged attachment SpatialBridge + bridge->setState(LLDrawable::MOVE_UNDAMPED); + bridge->updateMove(); + bridge->setState(LLDrawable::EARLY_MOVE); + } } + attached_object->updateText(); } } -- cgit v1.2.3 From 3dd841277e88be5c124605153fef0d13dfcd5767 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 27 Jan 2022 00:11:37 +0200 Subject: SL-16056 Avatar gas cloud adaptive delay #2 Reset avatar 'loaded' timer after getting new mesh data --- indra/newview/llvoavatar.cpp | 20 ++++++++++++++++++-- indra/newview/llvoavatar.h | 4 ++-- indra/newview/llvovolume.cpp | 12 ++++++++---- 3 files changed, 28 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 13ae43c7d6..56a895bd1f 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -127,6 +127,9 @@ const F32 MIN_HOVER_Z = -2.0; const F32 MIN_ATTACHMENT_COMPLEXITY = 0.f; const F32 DEFAULT_MAX_ATTACHMENT_COMPLEXITY = 1.0e6f; +// Unlike with 'self' avatar, server doesn't inform viewer about +// expected attachments so viewer has to wait to see if anything +// else will arrive const F32 FIRST_APPEARANCE_CLOUD_MIN_DELAY = 3.f; // seconds const F32 FIRST_APPEARANCE_CLOUD_MAX_DELAY = 45.f; @@ -746,7 +749,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mCurrentGesticulationLevel = 0; - mFirstSeenTimer.reset(); + mFirstAppearanceMessageTimer.reset(); mRuthTimer.reset(); mRuthDebugTimer.reset(); mDebugExistenceTimer.reset(); @@ -6434,6 +6437,16 @@ void LLVOAvatar::updateAttachmentOverrides() #endif } +void LLVOAvatar::notifyAttachmentMeshLoaded() +{ + if (!isFullyLoaded()) + { + // We just received mesh or skin info + // Reset timer to wait for more potential meshes or changes + mFullyLoadedTimer.reset(); + } +} + //----------------------------------------------------------------------------- // addAttachmentOverridesForObject //----------------------------------------------------------------------------- @@ -8156,7 +8169,7 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading) // Note that textures can causes 60s delay on thier own // so this delay might end up on top of textures' delay mFirstUseDelaySeconds = llclamp( - mFirstSeenTimer.getElapsedTimeF32(), + mFirstAppearanceMessageTimer.getElapsedTimeF32(), FIRST_APPEARANCE_CLOUD_MIN_DELAY, FIRST_APPEARANCE_CLOUD_MAX_DELAY); @@ -8926,6 +8939,9 @@ void LLVOAvatar::onFirstTEMessageReceived() mMeshTexturesDirty = TRUE; gPipeline.markGLRebuild(this); + + mFirstAppearanceMessageTimer.reset(); + mFullyLoadedTimer.reset(); } } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index ab2a2daf49..7c2d71802e 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -206,7 +206,7 @@ public: inline LLJoint* getSkeletonJoint(S32 joint_num) { return mSkeleton[joint_num]; } inline size_t getSkeletonJointCount() const { return mSkeleton.size(); } - + void notifyAttachmentMeshLoaded(); void addAttachmentOverridesForObject(LLViewerObject *vo, std::set* meshes_seen = NULL, bool recursive = true); void removeAttachmentOverridesForObject(const LLUUID& mesh_id); void removeAttachmentOverridesForObject(LLViewerObject *vo); @@ -379,7 +379,7 @@ protected: private: BOOL mFirstFullyVisible; F32 mFirstUseDelaySeconds; - LLFrameTimer mFirstSeenTimer; + LLFrameTimer mFirstAppearanceMessageTimer; BOOL mFullyLoaded; BOOL mPreviousFullyLoaded; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index e8bc015d78..8bc570311c 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1170,13 +1170,17 @@ void LLVOVolume::notifyMeshLoaded() mSculptChanged = TRUE; gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); - if (getAvatar() && !isAnimatedObject()) + LLVOAvatar *av = getAvatar(); + if (av && !isAnimatedObject()) { - getAvatar()->addAttachmentOverridesForObject(this); + av->addAttachmentOverridesForObject(this); + av->notifyAttachmentMeshLoaded(); } - if (getControlAvatar() && isAnimatedObject()) + LLControlAvatar *cav = getControlAvatar(); + if (cav && isAnimatedObject()) { - getControlAvatar()->addAttachmentOverridesForObject(this); + cav->addAttachmentOverridesForObject(this); + cav->notifyAttachmentMeshLoaded(); } updateVisualComplexity(); } -- cgit v1.2.3 From 12f21640c63af26c32965e3546668bbf1ee32389 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 27 Jan 2022 00:11:37 +0200 Subject: SL-16717 Rename RenderGLCoreProfile to prevent compatibility issues --- indra/newview/CMakeLists.txt | 2 ++ indra/newview/app_settings/settings.xml | 2 +- indra/newview/featuretable.txt | 6 +++--- indra/newview/featuretable_mac.txt | 2 +- indra/newview/llappviewer.cpp | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index ef7c628c71..24b7ab7441 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1693,6 +1693,8 @@ set(viewer_APPSETTINGS_FILES ${CMAKE_SOURCE_DIR}/../etc/message.xml ${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg packages-info.txt + featuretable.txt + featuretable_mac.txt ) source_group("App Settings" FILES ${viewer_APPSETTINGS_FILES}) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 0ccf74e923..41422d2330 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9842,7 +9842,7 @@ Value 2.2 - RenderGLCoreProfile + RenderGLContextCoreProfile Comment Don't use a compatibility profile OpenGL context. Requires restart. Basic shaders MUST be enabled. diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 4e56141fde..1ccde98283 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -70,7 +70,7 @@ RenderShadowDetail 1 2 RenderUseStreamVBO 1 1 RenderFSAASamples 1 16 RenderMaxTextureIndex 1 16 -RenderGLCoreProfile 1 1 +RenderGLContextCoreProfile 1 1 RenderGLMultiThreaded 1 1 @@ -314,12 +314,12 @@ list Intel RenderAnisotropic 1 0 RenderFSAASamples 1 0 RenderGLMultiThreaded 1 0 -RenderGLCoreProfile 1 0 +RenderGLContextCoreProfile 1 0 // AMD cards generally perform better when not using VBOs for streaming data // AMD cards also prefer an OpenGL Compatibility Profile Context list AMD RenderUseStreamVBO 1 0 -RenderGLCoreProfile 1 0 +RenderGLContextCoreProfile 1 0 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 13ede23a91..c9efd89cc8 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -70,7 +70,7 @@ RenderShadowDetail 1 2 RenderUseStreamVBO 1 1 RenderFSAASamples 1 16 RenderMaxTextureIndex 1 16 -RenderGLCoreProfile 1 0 +RenderGLContextCoreProfile 1 0 RenderGLMultiThreaded 1 0 // diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index a2391ef889..48f03245b8 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -532,7 +532,7 @@ static void settings_to_globals() LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize")); - LLRender::sGLCoreProfile = gSavedSettings.getBOOL("RenderGLCoreProfile"); + LLRender::sGLCoreProfile = gSavedSettings.getBOOL("RenderGLContextCoreProfile"); LLRender::sNsightDebugSupport = gSavedSettings.getBOOL("RenderNsightDebugSupport"); LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO"); LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic"); -- cgit v1.2.3 From af830e5fc5840194be95140f644a27011b9b7e06 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 28 Jan 2022 00:32:33 +0200 Subject: SL-16721 Crash at LLVOAvatar::idleUpdateMisc bridge in state 24 (dead) --- indra/newview/llvoavatar.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 56a895bd1f..2d34e28b93 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2825,7 +2825,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) //override rigged attachments' octree spatial extents with this avatar's bounding box LLSpatialBridge* bridge = attached_object->mDrawable->getSpatialBridge(); bool rigged = false; - if (bridge) + if (bridge && !bridge->isDead()) { //transform avatar bounding box into attachment's coordinate frame LLVector4a extents[2]; @@ -2842,7 +2842,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) attached_object->mDrawable->makeActive(); attached_object->mDrawable->updateXform(TRUE); - if (bridge) + if (bridge && !bridge->isDead()) { if (!rigged) { -- cgit v1.2.3 From c8926630af2b80c7db817b78df3a90378f0ecbbb Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Tue, 11 Jan 2022 17:29:04 -0700 Subject: SL-16418 optimize imageraw clear --- indra/llimage/llimage.cpp | 88 +++++++++++++++++++++++++---------------- indra/newview/llviewermedia.cpp | 41 +++++++++++-------- 2 files changed, 77 insertions(+), 52 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 15b07e5318..2855612158 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -925,47 +925,65 @@ bool LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height, void LLImageRaw::clear(U8 r, U8 g, U8 b, U8 a) { - llassert( getComponents() <= 4 ); - // This is fairly bogus, but it'll do for now. - if (isBufferInvalid()) - { - LL_WARNS() << "Invalid image buffer" << LL_ENDL; - return; - } + LL_PROFILE_ZONE_NAMED("djh imageraw clear") + S8 components = getComponents(); + llassert( components > 0 && components <= 4 ); - U8 *pos = getData(); - U32 x, y; - for (x = 0; x < getWidth(); x++) - { - for (y = 0; y < getHeight(); y++) - { - *pos = r; - pos++; - if (getComponents() == 1) - { - continue; - } - *pos = g; - pos++; - if (getComponents() == 2) - { - continue; - } - *pos = b; - pos++; - if (getComponents() == 3) - { - continue; - } - *pos = a; - pos++; - } - } + // This is fairly bogus, but it'll do for now. + if (isBufferInvalid()) + { + LL_WARNS() << "Invalid image buffer" << LL_ENDL; + return; + } + + switch (components) + { + case 1: + { + U8 *dst = getData(); + S32 count = getWidth() * getHeight(); + llassert(count == getDataSize()); + std::fill_n(dst, count, r); + break; + } + case 2: + { + U16 *dst = (U16 *)getData(); + S32 count = getWidth() * getHeight(); + llassert(count == getDataSize() / 2); + U16 val = (U16)(r | g << 8); + std::fill_n(dst, count, val); + break; + } + case 3: + { + U8 *dst = getData(); + S32 count = getWidth() * getHeight(); + llassert(count == getDataSize() / 3); + for (S32 i = 0; i < count; i++) + { + *dst++ = r; + *dst++ = g; + *dst++ = b; + } + break; + } + case 4: + { + U32 *dst = (U32 *)getData(); + S32 count = getWidth() * getHeight(); + llassert(count == getDataSize() / 4); + U32 val = (U32)(r | g << 8 | b << 16 | a << 24); + std::fill_n(dst, count, val); + break; + } + } } // Reverses the order of the rows in the image void LLImageRaw::verticalFlip() { + LL_PROFILE_ZONE_SCOPED; S32 row_bytes = getWidth() * getComponents(); llassert(row_bytes > 0); std::vector line_buffer(row_bytes); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 63f57e81cc..ba9bbcc57e 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -635,6 +635,7 @@ static bool proximity_comparitor(const LLViewerMediaImpl* i1, const LLViewerMedi static LLTrace::BlockTimerStatHandle FTM_MEDIA_UPDATE("Update Media"); static LLTrace::BlockTimerStatHandle FTM_MEDIA_SPARE_IDLE("Spare Idle"); static LLTrace::BlockTimerStatHandle FTM_MEDIA_UPDATE_INTEREST("Update/Interest"); +static LLTrace::BlockTimerStatHandle FTM_MEDIA_UPDATE_VOLUME("Update/Volume"); static LLTrace::BlockTimerStatHandle FTM_MEDIA_SORT("Media Sort"); static LLTrace::BlockTimerStatHandle FTM_MEDIA_SORT2("Media Sort 2"); static LLTrace::BlockTimerStatHandle FTM_MEDIA_MISC("Misc"); @@ -2087,6 +2088,7 @@ void LLViewerMediaImpl::setMute(bool mute) ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::updateVolume() { + LL_RECORD_BLOCK_TIME(FTM_MEDIA_UPDATE_VOLUME); if(mMediaSource) { // always scale the volume by the global media volume @@ -2943,7 +2945,7 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage() } LLViewerMediaTexture* placeholder_image = LLViewerTextureManager::getMediaTexture( mTextureId ); - + if (mNeedsNewTexture || placeholder_image->getUseMipMaps() || (placeholder_image->getWidth() != mMediaSource->getTextureWidth()) @@ -2960,25 +2962,30 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage() int texture_depth = mMediaSource->getTextureDepth(); // MEDIAOPT: check to see if size actually changed before doing work - placeholder_image->destroyGLTexture(); + placeholder_image->destroyGLTexture(); // MEDIAOPT: apparently just calling setUseMipMaps(FALSE) doesn't work? placeholder_image->reinit(FALSE); // probably not needed - // MEDIAOPT: seems insane that we actually have to make an imageraw then - // immediately discard it - LLPointer raw = new LLImageRaw(texture_width, texture_height, texture_depth); - // Clear the texture to the background color, ignoring alpha. - // convert background color channels from [0.0, 1.0] to [0, 255]; - raw->clear(int(mBackgroundColor.mV[VX] * 255.0f), int(mBackgroundColor.mV[VY] * 255.0f), int(mBackgroundColor.mV[VZ] * 255.0f), 0xff); - int discard_level = 0; - - // ask media source for correct GL image format constants - placeholder_image->setExplicitFormat(mMediaSource->getTextureFormatInternal(), - mMediaSource->getTextureFormatPrimary(), - mMediaSource->getTextureFormatType(), - mMediaSource->getTextureFormatSwapBytes()); - - placeholder_image->createGLTexture(discard_level, raw); + // MEDIAOPT: seems insane that we actually have to make an imageraw then + // immediately discard it + LLPointer raw = new LLImageRaw(texture_width, texture_height, texture_depth); + // Clear the texture to the background color, ignoring alpha. + // convert background color channels from [0.0, 1.0] to [0, 255]; + {LL_PROFILE_ZONE_NAMED("djh clear raw"); + raw->clear(int(mBackgroundColor.mV[VX] * 255.0f), int(mBackgroundColor.mV[VY] * 255.0f), int(mBackgroundColor.mV[VZ] * 255.0f), 0xff); + } + // ask media source for correct GL image format constants + {LL_PROFILE_ZONE_NAMED("djh setformat raw"); + placeholder_image->setExplicitFormat(mMediaSource->getTextureFormatInternal(), + mMediaSource->getTextureFormatPrimary(), + mMediaSource->getTextureFormatType(), + mMediaSource->getTextureFormatSwapBytes()); + } + { + LL_PROFILE_ZONE_NAMED("djh create ph"); + int discard_level = 0; + placeholder_image->createGLTexture(discard_level, raw); + } // MEDIAOPT: set this dynamically on play/stop // FIXME -- cgit v1.2.3 From 7dcca7f180c2204daefbc3648ebe766a46c7cf85 Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Fri, 14 Jan 2022 10:34:21 -0700 Subject: SL-16418 bg thread for media texture updates --- indra/newview/llviewermedia.cpp | 179 +++++++++++++++++++++++++++++---------- indra/newview/llviewermedia.h | 36 +++++++- indra/newview/llviewerwindow.cpp | 6 +- 3 files changed, 176 insertions(+), 45 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index ba9bbcc57e..8515d61f64 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -78,6 +78,9 @@ #include // for SkinFolder listener #include +// Statics +bool LLMediaTextureUpdateThread::sEnabled = false; + class LLMediaFilePicker : public LLFilePickerThread // deletes itself when done { public: @@ -1591,6 +1594,8 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, media_tex->setMediaImpl(); } + mMainQueue = LL::WorkQueue::getInstance("mainloop"); + mTexUpdateQueue = LL::WorkQueue::getInstance("LLMediaTextureUpdate"); // Share work queue with tex loader. } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1604,6 +1609,25 @@ LLViewerMediaImpl::~LLViewerMediaImpl() remove_media_impl(this); } +////////////////////////////////////////////////////////////////////////////////////////// +//static +void LLViewerMediaImpl::initClass(LLWindow* window, bool multi_threaded /* = false */) +{ + LL_PROFILE_ZONE_SCOPED; + if (multi_threaded) + { + LLMediaTextureUpdateThread::createInstance(window); + } +} + +////////////////////////////////////////////////////////////////////////////////////////// +//static +void LLViewerMediaImpl::cleanupClass() +{ + LL_PROFILE_ZONE_SCOPED; + LLMediaTextureUpdateThread::deleteSingleton(); +} + ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::emitEvent(LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event) { @@ -2876,65 +2900,108 @@ void LLViewerMediaImpl::update() return; } - LLViewerMediaTexture* placeholder_image = updatePlaceholderImage(); + ref(); - if(placeholder_image) - { - LLRect dirty_rect; + if (preUpdateMediaTexture()) + { + // Push update to worker thread + auto main_queue = LLMediaTextureUpdateThread::sEnabled ? mMainQueue.lock() : nullptr; + if (main_queue) + { + main_queue->postTo( + mTexUpdateQueue, // Worker thread queue + [this]() // work done on update worker thread + { + doMediaTexUpdate(); + }, + [this]() // callback to main thread + { + postUpdateMediaTexture(); + //unref(); + }); + } + else + { + doMediaTexUpdate(); // otherwise, update on main thread + //unref(); + } + } + unref(); - // Since we're updating this texture, we know it's playing. Tell the texture to do its replacement magic so it gets rendered. - placeholder_image->setPlaying(TRUE); +} - if(mMediaSource->getDirty(&dirty_rect)) - { - // Constrain the dirty rect to be inside the texture - S32 x_pos = llmax(dirty_rect.mLeft, 0); - S32 y_pos = llmax(dirty_rect.mBottom, 0); - S32 width = llmin(dirty_rect.mRight, placeholder_image->getWidth()) - x_pos; - S32 height = llmin(dirty_rect.mTop, placeholder_image->getHeight()) - y_pos; +////////////////////////////////////////////////////////////////////////////////////////// +bool LLViewerMediaImpl::preUpdateMediaTexture() +{ + return true; +} - if(width > 0 && height > 0) - { +////////////////////////////////////////////////////////////////////////////////////////// +bool LLViewerMediaImpl::postUpdateMediaTexture() +{ + return true; +} - U8* data = NULL; - { - LL_PROFILE_ZONE_NAMED_CATEGORY_MEDIA("media get data"); //LL_RECORD_BLOCK_TIME(FTM_MEDIA_GET_DATA); - data = mMediaSource->getBitsData(); - } +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::doMediaTexUpdate() +{ + LLViewerMediaTexture* placeholder_image = updatePlaceholderImage(); - if(data != NULL) - { - // Offset the pixels pointer to match x_pos and y_pos - data += ( x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth() ); - data += ( y_pos * mMediaSource->getTextureDepth() ); + if (placeholder_image) + { + LLRect dirty_rect; - { - LL_PROFILE_ZONE_NAMED_CATEGORY_MEDIA("media set subimage"); //LL_RECORD_BLOCK_TIME(FTM_MEDIA_SET_SUBIMAGE); - placeholder_image->setSubImage( - data, - mMediaSource->getBitsWidth(), - mMediaSource->getBitsHeight(), - x_pos, - y_pos, - width, - height); - } - } + // Since we're updating this texture, we know it's playing. Tell the texture to do its replacement magic so it gets rendered. + placeholder_image->setPlaying(TRUE); - } + if (mMediaSource->getDirty(&dirty_rect)) + { + // Constrain the dirty rect to be inside the texture + S32 x_pos = llmax(dirty_rect.mLeft, 0); + S32 y_pos = llmax(dirty_rect.mBottom, 0); + S32 width = llmin(dirty_rect.mRight, placeholder_image->getWidth()) - x_pos; + S32 height = llmin(dirty_rect.mTop, placeholder_image->getHeight()) - y_pos; - mMediaSource->resetDirty(); - } - } -} + if (width > 0 && height > 0) + { + U8* data = NULL; + { + LL_RECORD_BLOCK_TIME(FTM_MEDIA_GET_DATA); + data = mMediaSource->getBitsData(); + } + + if (data != NULL) + { + // Offset the pixels pointer to match x_pos and y_pos + data += (x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth()); + data += (y_pos * mMediaSource->getTextureDepth()); + + { + LL_RECORD_BLOCK_TIME(FTM_MEDIA_SET_SUBIMAGE); + placeholder_image->setSubImage( + data, + mMediaSource->getBitsWidth(), + mMediaSource->getBitsHeight(), + x_pos, + y_pos, + width, + height); + } + } + + } + + mMediaSource->resetDirty(); + } + } +} ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::updateImagesMediaStreams() { } - ////////////////////////////////////////////////////////////////////////////////////////// LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage() { @@ -3927,3 +3994,29 @@ bool LLViewerMediaImpl::isObjectInAgentParcel(LLVOVolume *obj) { return (LLViewerParcelMgr::getInstance()->inAgentParcel(obj->getPositionGlobal())); } + +LLMediaTextureUpdateThread::LLMediaTextureUpdateThread(LLWindow* window) +// We want exactly one thread, of moderate capacity: there are likely only a handful +// of media texture frames in-flight at any one time + : ThreadPool("LLMediaTextureUpdate", 1, 4096) + , mWindow(window) +{ + LL_PROFILE_ZONE_SCOPED; + sEnabled = true; + mFinished = false; + + mContext = mWindow->createSharedContext(); + ThreadPool::start(); +} + +void LLMediaTextureUpdateThread::run() +{ + LL_PROFILE_ZONE_SCOPED; + // We must perform setup on this thread before actually servicing our + // WorkQueue, likewise cleanup afterwards. + mWindow->makeContextCurrent(mContext); + gGL.init(); + ThreadPool::run(); + gGL.shutdown(); + mWindow->destroySharedContext(mContext); +} diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 71cec5125d..c2e6564166 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -197,7 +197,10 @@ public: U8 media_loop); ~LLViewerMediaImpl(); - + + static void initClass(LLWindow* window, bool multi_threaded = false); + static void cleanupClass(); + // Override inherited version from LLViewerMediaEventEmitter virtual void emitEvent(LLPluginClassMedia* self, LLViewerMediaObserver::EMediaEvent event); @@ -266,6 +269,9 @@ public: void scaleTextureCoords(const LLVector2& texture_coords, S32 *x, S32 *y); void update(); + bool preUpdateMediaTexture(); + void doMediaTexUpdate(); + bool postUpdateMediaTexture(); void updateImagesMediaStreams(); LLUUID getMediaTextureID() const; @@ -490,6 +496,34 @@ private: private: LLViewerMediaTexture *updatePlaceholderImage(); + LL::WorkQueue::weak_t mMainQueue; + LL::WorkQueue::weak_t mTexUpdateQueue; + +}; + +// Define a worker thread pool for media updates ( LLImageGLThread) +class LLMediaTextureUpdateThread : public LLSimpleton, LL::ThreadPool +{ +public: + // follows gSavedSettings "RenderGLMultiThreaded" + static bool sEnabled; + + LLMediaTextureUpdateThread(LLWindow* window); + + // post a function to be executed on the LLMediaTextureUpdateThread background thread + template + bool post(CALLABLE&& func) + { + return getQueue().postIfOpen(std::forward(func)); + } + + void run() override; + +private: + LLWindow* mWindow; + void* mContext = nullptr; + LLAtomicBool mFinished; }; + #endif // LLVIEWERMEDIA_H diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index b9a5e90df0..ba93f4f5f9 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2027,6 +2027,9 @@ LLViewerWindow::LLViewerWindow(const Params& p) gTextureList.init(); LLViewerTextureManager::init() ; gBumpImageList.init(); + + // Init Media texture worker queue + LLViewerMediaImpl::initClass(mWindow, gSavedSettings.getBOOL("RenderGLMultiThreaded")); // Create container for all sub-views LLView::Params rvp; @@ -2416,7 +2419,8 @@ void LLViewerWindow::shutdownGL() LLViewerTextureManager::cleanup() ; SUBSYSTEM_CLEANUP(LLImageGL) ; - + SUBSYSTEM_CLEANUP(LLViewerMediaImpl); + LL_INFOS() << "All textures and llimagegl images are destroyed!" << LL_ENDL ; LL_INFOS() << "Cleaning up select manager" << LL_ENDL; -- cgit v1.2.3 From 8d0efb54db96c87a2adb4a824998870ff397846e Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Thu, 27 Jan 2022 12:57:30 -0700 Subject: SL-16418 rename media tex image per-update to avoid contention stall --- indra/llimage/llimage.cpp | 2 +- indra/llrender/llimagegl.cpp | 66 ++++++-- indra/llrender/llimagegl.h | 10 +- indra/newview/llviewermedia.cpp | 331 +++++++++++++++++++------------------- indra/newview/llviewermedia.h | 7 +- indra/newview/llviewertexture.cpp | 1 + 6 files changed, 234 insertions(+), 183 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 2855612158..fb02a131fd 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -925,7 +925,7 @@ bool LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height, void LLImageRaw::clear(U8 r, U8 g, U8 b, U8 a) { - LL_PROFILE_ZONE_NAMED("djh imageraw clear") + LL_PROFILE_ZONE_SCOPED; S8 components = getComponents(); llassert( components > 0 && components <= 4 ); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 1e9b9f642e..4b4f071171 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1215,9 +1215,8 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE) { //GL_ALPHA is deprecated, convert to RGBA use_scratch = true; - scratch = new U32[width * height]; - U32 pixel_count = (U32)(width * height); + scratch = new U32[pixel_count]; for (U32 i = 0; i < pixel_count; i++) { U8* pix = (U8*)&scratch[i]; @@ -1232,9 +1231,8 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE) { //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA use_scratch = true; - scratch = new U32[width * height]; - U32 pixel_count = (U32)(width * height); + scratch = new U32[pixel_count]; for (U32 i = 0; i < pixel_count; i++) { U8 lum = ((U8*)pixels)[i * 2 + 0]; @@ -1252,9 +1250,8 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE) { //GL_LUMINANCE_ALPHA is deprecated, convert to RGB use_scratch = true; - scratch = new U32[width * height]; - U32 pixel_count = (U32)(width * height); + scratch = new U32[pixel_count]; for (U32 i = 0; i < pixel_count; i++) { U8 lum = ((U8*)pixels)[i]; @@ -1314,10 +1311,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt } stop_glerror(); - if (use_scratch) - { - delete[] scratch; - } + if (scratch) delete[] scratch; } //create an empty GL texture: just create a texture name @@ -1471,7 +1465,49 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S return createGLTexture(discard_level, rawdata, FALSE, usename); } -BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) +// Create a new GL name and allocate tex storage (unitialized) for it +// Used to break resource contention stall in background media tex updates +void LLImageGL::allocNewTexName() +{ + LL_PROFILE_ZONE_SCOPED; + if (on_main_thread()) return; // Should only be called on bg update thread + if (!mGLTextureCreated) return; + if (0 != mNewTexName) return; // only 1 rename in flight at a time + + generateTextures(1, &mNewTexName); // create new GL name + + mHasMipMaps = false; // Media textures aren't mipped + mMipLevels = 0; + // Set state to match current + gGL.getTexUnit(0)->bind(this, false, false, mNewTexName); + glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel); + glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_WIDTH, mWidth); + glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_HEIGHT, mHeight); + gGL.getTexUnit(0)->setHasMipMaps(mHasMipMaps); + gGL.getTexUnit(0)->setTextureAddressMode(mAddressMode); + gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption); + + setManualImage(mTarget, 0, mFormatInternal, mWidth, mHeight, mFormatPrimary, mFormatType, + (GLvoid *) nullptr, mAllowCompression); + + gGL.getTexUnit(0)->unbind(mBindTarget); + + mLastBindTime = sLastFrameTime; +} + +// Delete no-longer-needed GL tex name (on main thread) +void LLImageGL::swapTexName() +{ + if (mNewTexName) + { + deleteTextures(1, &mTexName); + mTexName = mNewTexName; + mNewTexName = 0; + } +} + +BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips /* = FALSE */, S32 usename /* = 0 */) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; checkActiveThread(); @@ -1715,6 +1751,14 @@ void LLImageGL::destroyGLTexture() mTexName = 0; mGLTextureCreated = FALSE ; } + + // clean up any in-flight name change + if (0 != mNewTexName) + { + // Memory is transient, not tracked by sGlobalTextuerMemory + LLImageGL::deleteTextures(1, &mNewTexName); + mNewTexName = 0; + } } //force to invalidate the gl texture, most likely a sculpty texture diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index d6f4b13a51..f311170823 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -109,15 +109,17 @@ public: static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression = true); BOOL createGLTexture() ; - BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, - S32 category = sMaxCategories-1); + BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = sMaxCategories-1); BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0); - void setImage(const LLImageRaw* imageraw); + void setImage(const LLImageRaw* imageraw); BOOL setImage(const U8* data_in, BOOL data_hasmips = FALSE, S32 usename = 0); BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height); - + + void allocNewTexName(); + void swapTexName(); + // Read back a raw image for this discard level, if it exists BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const; void destroyGLTexture(); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 8515d61f64..de7aaf3173 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -39,6 +39,7 @@ #include "llfilepicker.h" #include "llfloaterwebcontent.h" // for handling window close requests and geometry change requests in media browser windows. #include "llfocusmgr.h" +#include "llimagegl.h" #include "llkeyboard.h" #include "lllogininstance.h" #include "llmarketplacefunctions.h" @@ -2824,165 +2825,156 @@ static LLTrace::BlockTimerStatHandle FTM_MEDIA_SET_SUBIMAGE("Set Subimage"); void LLViewerMediaImpl::update() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; //LL_RECORD_BLOCK_TIME(FTM_MEDIA_DO_UPDATE); - if(mMediaSource == NULL) - { - if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED) - { - // This media source should not be loaded. - } - else if(mPriority <= LLPluginClassMedia::PRIORITY_SLIDESHOW) - { - // Don't load new instances that are at PRIORITY_SLIDESHOW or below. They're just kept around to preserve state. - } + LL_RECORD_BLOCK_TIME(FTM_MEDIA_DO_UPDATE); + if(mMediaSource == NULL) + { + if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED) + { + // This media source should not be loaded. + } + else if(mPriority <= LLPluginClassMedia::PRIORITY_SLIDESHOW) + { + // Don't load new instances that are at PRIORITY_SLIDESHOW or below. They're just kept around to preserve state. + } else if (!mMimeProbe.expired()) - { - // this media source is doing a MIME type probe -- don't try loading it again. - } - else - { - // This media may need to be loaded. - if(sMediaCreateTimer.hasExpired()) - { - LL_DEBUGS("PluginPriority") << this << ": creating media based on timer expiration" << LL_ENDL; - createMediaSource(); - sMediaCreateTimer.setTimerExpirySec(LLVIEWERMEDIA_CREATE_DELAY); - } - else - { - LL_DEBUGS("PluginPriority") << this << ": NOT creating media (waiting on timer)" << LL_ENDL; - } - } - } - else - { - updateVolume(); - - // TODO: this is updated every frame - is this bad? - // Removing this as part of the post viewer64 media update - // Removed as not implemented in CEF embedded browser - // See MAINT-8194 for a more fuller description - // updateJavascriptObject(); - } - - - if(mMediaSource == NULL) - { - return; - } + { + // this media source is doing a MIME type probe -- don't try loading it again. + } + else + { + // This media may need to be loaded. + if(sMediaCreateTimer.hasExpired()) + { + LL_DEBUGS("PluginPriority") << this << ": creating media based on timer expiration" << LL_ENDL; + createMediaSource(); + sMediaCreateTimer.setTimerExpirySec(LLVIEWERMEDIA_CREATE_DELAY); + } + else + { + LL_DEBUGS("PluginPriority") << this << ": NOT creating media (waiting on timer)" << LL_ENDL; + } + } + } + else + { + updateVolume(); - // Make sure a navigate doesn't happen during the idle -- it can cause mMediaSource to get destroyed, which can cause a crash. - setNavigateSuspended(true); + // TODO: this is updated every frame - is this bad? + // Removing this as part of the post viewer64 media update + // Removed as not implemented in CEF embedded browser + // See MAINT-8194 for a more fuller description + // updateJavascriptObject(); + } - mMediaSource->idle(); - setNavigateSuspended(false); + if(mMediaSource == NULL) + { + return; + } - if(mMediaSource == NULL) - { - return; - } + // Make sure a navigate doesn't happen during the idle -- it can cause mMediaSource to get destroyed, which can cause a crash. + setNavigateSuspended(true); - if(mMediaSource->isPluginExited()) - { - resetPreviousMediaState(); - destroyMediaSource(); - return; - } + mMediaSource->idle(); - if(!mMediaSource->textureValid()) - { - return; - } + setNavigateSuspended(false); - if(mSuspendUpdates || !mVisible) - { - return; - } + if(mMediaSource == NULL) + { + return; + } - ref(); + if(mMediaSource->isPluginExited()) + { + resetPreviousMediaState(); + destroyMediaSource(); + return; + } - if (preUpdateMediaTexture()) + if(!mMediaSource->textureValid()) { - // Push update to worker thread - auto main_queue = LLMediaTextureUpdateThread::sEnabled ? mMainQueue.lock() : nullptr; - if (main_queue) - { - main_queue->postTo( - mTexUpdateQueue, // Worker thread queue - [this]() // work done on update worker thread - { - doMediaTexUpdate(); - }, - [this]() // callback to main thread - { - postUpdateMediaTexture(); - //unref(); - }); - } - else - { - doMediaTexUpdate(); // otherwise, update on main thread - //unref(); - } + return; } - unref(); -} + if(mSuspendUpdates || !mVisible) + { + return; + } -////////////////////////////////////////////////////////////////////////////////////////// -bool LLViewerMediaImpl::preUpdateMediaTexture() -{ - return true; -} -////////////////////////////////////////////////////////////////////////////////////////// -bool LLViewerMediaImpl::postUpdateMediaTexture() -{ - return true; + // Push update to worker thread + auto main_queue = LLMediaTextureUpdateThread::sEnabled ? mMainQueue.lock() : nullptr; + ref(); // protect texture from deletion while active on bg queue + if (main_queue) + { + // replace GL name + //llassert(!mTextureId.isNull()); + //LLImageGL* base_image = LLViewerTextureManager::getMediaTexture(mTextureId)->getGLTexture(); + //GLuint retired_name = base_image->allocNew(); + main_queue->postTo( + mTexUpdateQueue, // Worker thread queue + [this]() // work done on update worker thread + { + doMediaTexUpdate(); + }, + [this]() // callback to main thread + { + endMediaTexUpdate(); + unref(); + }); + } + else + { + doMediaTexUpdate(); // otherwise, update on main thread + unref(); + } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::doMediaTexUpdate() { - LLViewerMediaTexture* placeholder_image = updatePlaceholderImage(); - if (placeholder_image) + LLViewerMediaTexture* media_tex = updateMediaImage(); + + if (media_tex && mMediaSource) { + llassert(mMediaSource); + LLRect dirty_rect; + S32 media_width = mMediaSource->getTextureWidth(); + S32 media_height = mMediaSource->getTextureHeight(); + S32 media_depth = mMediaSource->getTextureDepth(); // Since we're updating this texture, we know it's playing. Tell the texture to do its replacement magic so it gets rendered. - placeholder_image->setPlaying(TRUE); + media_tex->setPlaying(TRUE); if (mMediaSource->getDirty(&dirty_rect)) { // Constrain the dirty rect to be inside the texture S32 x_pos = llmax(dirty_rect.mLeft, 0); S32 y_pos = llmax(dirty_rect.mBottom, 0); - S32 width = llmin(dirty_rect.mRight, placeholder_image->getWidth()) - x_pos; - S32 height = llmin(dirty_rect.mTop, placeholder_image->getHeight()) - y_pos; + S32 width = llmin(dirty_rect.mRight, media_width) - x_pos; + S32 height = llmin(dirty_rect.mTop, media_height) - y_pos; if (width > 0 && height > 0) { - U8* data = NULL; - { - LL_RECORD_BLOCK_TIME(FTM_MEDIA_GET_DATA); - data = mMediaSource->getBitsData(); - } + S32 data_width = mMediaSource->getBitsWidth(); + S32 data_height = mMediaSource->getBitsHeight(); + data = mMediaSource->getBitsData(); if (data != NULL) { // Offset the pixels pointer to match x_pos and y_pos - data += (x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth()); - data += (y_pos * mMediaSource->getTextureDepth()); + data += (x_pos * media_depth * data_width); + data += (y_pos * media_depth); { LL_RECORD_BLOCK_TIME(FTM_MEDIA_SET_SUBIMAGE); - placeholder_image->setSubImage( + media_tex->setSubImage( data, - mMediaSource->getBitsWidth(), - mMediaSource->getBitsHeight(), + data_width, + data_height, x_pos, y_pos, width, @@ -2997,75 +2989,87 @@ void LLViewerMediaImpl::doMediaTexUpdate() } } +////////////////////////////////////////////////////////////////////////////////////////// +// runs on main thread, but only called when bg thread updates are active +void LLViewerMediaImpl::endMediaTexUpdate() +{ + LLViewerMediaTexture* base_image = LLViewerTextureManager::findMediaTexture(mTextureId); + llassert(base_image); + + LLImageGL* image = base_image->getGLTexture(); + image->swapTexName(); // retire old GL name +} + ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::updateImagesMediaStreams() { } ////////////////////////////////////////////////////////////////////////////////////////// -LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage() +LLViewerMediaTexture* LLViewerMediaImpl::updateMediaImage() { - if(mTextureId.isNull()) - { - // The code that created this instance will read from the plugin's bits. - return NULL; - } + if (!mMediaSource) + { + return nullptr; // not ready for updating + } - LLViewerMediaTexture* placeholder_image = LLViewerTextureManager::getMediaTexture( mTextureId ); - - if (mNeedsNewTexture - || placeholder_image->getUseMipMaps() - || (placeholder_image->getWidth() != mMediaSource->getTextureWidth()) - || (placeholder_image->getHeight() != mMediaSource->getTextureHeight()) - || (mTextureUsedWidth != mMediaSource->getWidth()) - || (mTextureUsedHeight != mMediaSource->getHeight()) - ) - { - LL_DEBUGS("Media") << "initializing media placeholder" << LL_ENDL; - LL_DEBUGS("Media") << "movie image id " << mTextureId << LL_ENDL; - - int texture_width = mMediaSource->getTextureWidth(); - int texture_height = mMediaSource->getTextureHeight(); - int texture_depth = mMediaSource->getTextureDepth(); - - // MEDIAOPT: check to see if size actually changed before doing work - placeholder_image->destroyGLTexture(); - // MEDIAOPT: apparently just calling setUseMipMaps(FALSE) doesn't work? - placeholder_image->reinit(FALSE); // probably not needed + llassert(!mTextureId.isNull()); + LLViewerMediaTexture* media_tex = LLViewerTextureManager::getMediaTexture( mTextureId ); + + // if on bg thread, create new GL tex image resource to avoid resource contention + if (!on_main_thread()) + { + LLImageGL* image = media_tex->getGLTexture(); + image->allocNewTexName(); + } + + if ( mNeedsNewTexture + || media_tex->getUseMipMaps() + || (media_tex->getWidth() != mMediaSource->getTextureWidth()) + || (media_tex->getHeight() != mMediaSource->getTextureHeight()) + || (mTextureUsedWidth != mMediaSource->getWidth()) + || (mTextureUsedHeight != mMediaSource->getHeight()) + ) + { + LL_DEBUGS("Media") << "initializing media placeholder" << LL_ENDL; + LL_DEBUGS("Media") << "movie image id " << mTextureId << LL_ENDL; + + int texture_width = mMediaSource->getTextureWidth(); + int texture_height = mMediaSource->getTextureHeight(); + int texture_depth = mMediaSource->getTextureDepth(); + + // MEDIAOPT: check to see if size actually changed before doing work + media_tex->destroyGLTexture(); + // MEDIAOPT: apparently just calling setUseMipMaps(FALSE) doesn't work? + media_tex->reinit(FALSE); // probably not needed // MEDIAOPT: seems insane that we actually have to make an imageraw then // immediately discard it LLPointer raw = new LLImageRaw(texture_width, texture_height, texture_depth); // Clear the texture to the background color, ignoring alpha. // convert background color channels from [0.0, 1.0] to [0, 255]; - {LL_PROFILE_ZONE_NAMED("djh clear raw"); raw->clear(int(mBackgroundColor.mV[VX] * 255.0f), int(mBackgroundColor.mV[VY] * 255.0f), int(mBackgroundColor.mV[VZ] * 255.0f), 0xff); - } + // ask media source for correct GL image format constants - {LL_PROFILE_ZONE_NAMED("djh setformat raw"); - placeholder_image->setExplicitFormat(mMediaSource->getTextureFormatInternal(), + media_tex->setExplicitFormat(mMediaSource->getTextureFormatInternal(), mMediaSource->getTextureFormatPrimary(), mMediaSource->getTextureFormatType(), mMediaSource->getTextureFormatSwapBytes()); - } - { - LL_PROFILE_ZONE_NAMED("djh create ph"); - int discard_level = 0; - placeholder_image->createGLTexture(discard_level, raw); - } - // MEDIAOPT: set this dynamically on play/stop - // FIXME -// placeholder_image->mIsMediaTexture = true; - mNeedsNewTexture = false; + int discard_level = 0; + media_tex->createGLTexture(discard_level, raw); - // If the amount of the texture being drawn by the media goes down in either width or height, - // recreate the texture to avoid leaving parts of the old image behind. - mTextureUsedWidth = mMediaSource->getWidth(); - mTextureUsedHeight = mMediaSource->getHeight(); - } + // MEDIAOPT: set this dynamically on play/stop + // FIXME +// media_tex->mIsMediaTexture = true; + mNeedsNewTexture = false; - return placeholder_image; + // If the amount of the texture being drawn by the media goes down in either width or height, + // recreate the texture to avoid leaving parts of the old image behind. + mTextureUsedWidth = mMediaSource->getWidth(); + mTextureUsedHeight = mMediaSource->getHeight(); + } + return media_tex; } @@ -4017,6 +4021,7 @@ void LLMediaTextureUpdateThread::run() mWindow->makeContextCurrent(mContext); gGL.init(); ThreadPool::run(); + LLMediaTextureUpdateThread::sEnabled = false; gGL.shutdown(); mWindow->destroySharedContext(mContext); } diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index c2e6564166..03a14421ff 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -269,9 +269,8 @@ public: void scaleTextureCoords(const LLVector2& texture_coords, S32 *x, S32 *y); void update(); - bool preUpdateMediaTexture(); void doMediaTexUpdate(); - bool postUpdateMediaTexture(); + void endMediaTexUpdate(); void updateImagesMediaStreams(); LLUUID getMediaTextureID() const; @@ -495,13 +494,13 @@ private: bool mCanceling; private: - LLViewerMediaTexture *updatePlaceholderImage(); + LLViewerMediaTexture *updateMediaImage(); LL::WorkQueue::weak_t mMainQueue; LL::WorkQueue::weak_t mTexUpdateQueue; }; -// Define a worker thread pool for media updates ( LLImageGLThread) +// Define a worker thread pool for media updates (ref LLImageGLThread) class LLMediaTextureUpdateThread : public LLSimpleton, LL::ThreadPool { public: diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 5fed46f437..d652b76794 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1643,6 +1643,7 @@ void LLViewerFetchedTexture::scheduleCreateTexture() #endif mNeedsCreateTexture = TRUE; auto mainq = LLImageGLThread::sEnabled ? mMainQueue.lock() : nullptr; + ref(); // protect texture from deletion while active on bg queue if (mainq) { mainq->postTo( -- cgit v1.2.3 From 7f1832c1ca0a18f34ba993f58ab2e05360bb36fd Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Thu, 27 Jan 2022 15:41:24 -0700 Subject: SL-16418 restore tracy macros stomped in merge --- indra/newview/llviewermedia.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index de7aaf3173..6c04321539 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -2825,7 +2825,7 @@ static LLTrace::BlockTimerStatHandle FTM_MEDIA_SET_SUBIMAGE("Set Subimage"); void LLViewerMediaImpl::update() { - LL_RECORD_BLOCK_TIME(FTM_MEDIA_DO_UPDATE); + LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; //LL_RECORD_BLOCK_TIME(FTM_MEDIA_DO_UPDATE); if(mMediaSource == NULL) { if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED) @@ -2933,7 +2933,7 @@ void LLViewerMediaImpl::update() ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::doMediaTexUpdate() { - + LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; LLViewerMediaTexture* media_tex = updateMediaImage(); if (media_tex && mMediaSource) @@ -2970,7 +2970,7 @@ void LLViewerMediaImpl::doMediaTexUpdate() data += (y_pos * media_depth); { - LL_RECORD_BLOCK_TIME(FTM_MEDIA_SET_SUBIMAGE); + LL_PROFILE_ZONE_NAMED_CATEGORY_MEDIA("media set subimage"); //LL_RECORD_BLOCK_TIME(FTM_MEDIA_SET_SUBIMAGE); media_tex->setSubImage( data, data_width, @@ -2993,6 +2993,7 @@ void LLViewerMediaImpl::doMediaTexUpdate() // runs on main thread, but only called when bg thread updates are active void LLViewerMediaImpl::endMediaTexUpdate() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; LLViewerMediaTexture* base_image = LLViewerTextureManager::findMediaTexture(mTextureId); llassert(base_image); @@ -3008,6 +3009,7 @@ void LLViewerMediaImpl::updateImagesMediaStreams() ////////////////////////////////////////////////////////////////////////////////////////// LLViewerMediaTexture* LLViewerMediaImpl::updateMediaImage() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; if (!mMediaSource) { return nullptr; // not ready for updating -- cgit v1.2.3 From c76f8f7bcc69b13885f22d425a1f29d3446c4c2a Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Thu, 27 Jan 2022 17:25:42 -0700 Subject: SL-16418 remove duplicated ref() --- indra/newview/llviewertexture.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index d652b76794..ccf4c5bbec 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1629,7 +1629,6 @@ void LLViewerFetchedTexture::scheduleCreateTexture() mNeedsCreateTexture = TRUE; if (preCreateTexture()) { - ref(); #if LL_IMAGEGL_THREAD_CHECK //grab a copy of the raw image data to make sure it isn't modified pending texture creation U8* data = mRawImage->getData(); -- cgit v1.2.3 From d28a271fa819c076e2cedb87d9f305468e436b25 Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Fri, 28 Jan 2022 09:43:21 -0700 Subject: SL-16418 add some big-endian future-proofing --- indra/llimage/llimage.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'indra') diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index fb02a131fd..ba7ee0b465 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -951,7 +951,11 @@ void LLImageRaw::clear(U8 r, U8 g, U8 b, U8 a) U16 *dst = (U16 *)getData(); S32 count = getWidth() * getHeight(); llassert(count == getDataSize() / 2); +#ifdef LL_LITTLE_ENDIAN U16 val = (U16)(r | g << 8); +#else + U16 val = (U16)(r << 8 | g); +#endif std::fill_n(dst, count, val); break; } @@ -973,7 +977,11 @@ void LLImageRaw::clear(U8 r, U8 g, U8 b, U8 a) U32 *dst = (U32 *)getData(); S32 count = getWidth() * getHeight(); llassert(count == getDataSize() / 4); +#ifdef LL_LITTLE_ENDIAN U32 val = (U32)(r | g << 8 | b << 16 | a << 24); +#else + U32 val = (U32)(r << 24 | g << 16 | b << 8 | a); +#endif std::fill_n(dst, count, val); break; } -- cgit v1.2.3 From 6344c6f81dd098d6c38b727993f1cf0a6193e37d Mon Sep 17 00:00:00 2001 From: Runitai Linden Date: Fri, 28 Jan 2022 14:41:55 -0600 Subject: SL-16696 Hacky fix for disappearing underwater objects. --- indra/newview/pipeline.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index dd9999d73a..117766afea 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -9325,7 +9325,11 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLColor3 col = LLEnvironment::instance().getCurrentWater()->getWaterFogColor(); glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f); - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER1; + // HACK FIX -- pretend underwater camera is the world camera to fix weird visibility artifacts + // during distortion render (doesn't break main render because the camera is the same perspective + // as world camera and occlusion culling is disabled for this pass) + //LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER1; + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; mWaterDis.bindTarget(); mWaterDis.getViewport(gGLViewport); -- cgit v1.2.3 From d38a273014b672e6dedd8608c9f24dfb43e028ea Mon Sep 17 00:00:00 2001 From: Ptolemy Date: Fri, 28 Jan 2022 18:05:18 -0800 Subject: SL-16722 Fix void water not being rendered due to PR 782 skipping second pass of water rendering --- indra/newview/lldrawpoolwater.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 0f2bcf4708..6762b38c39 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -520,9 +520,10 @@ void LLDrawPoolWater::renderWater() LLColor4 specular(sun_up ? psky->getSunlightColor() : psky->getMoonlightColor()); F32 phase_time = (F32) LLFrameTimer::getElapsedSeconds() * 0.5f; - bool edge = false; LLGLSLShader *shader = nullptr; - do // twice through, once with normal shader bound & once with edge shader bound + + // two passes, first with standard water shader bound, second with edge water shader bound + for( int edge = 0 ; edge < 2; edge++ ) { // select shader if (underwater && LLPipeline::sWaterReflections) @@ -675,7 +676,7 @@ void LLDrawPoolWater::renderWater() gGL.getTexUnit(diffTex)->bind(face->getTexture()); - if (edge == (bool) water->getIsEdgePatch()) + if ((bool)edge == (bool) water->getIsEdgePatch()) { face->renderIndexed(); @@ -699,9 +700,7 @@ void LLDrawPoolWater::renderWater() shader->unbind(); gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE); - - edge = !edge; - } while (!edge); + } gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); -- cgit v1.2.3 From 25370e10b66231ff95086f0104c6aee641876763 Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Mon, 31 Jan 2022 16:38:53 -0700 Subject: SL-16418 add tear-down lock --- indra/newview/llviewermedia.cpp | 12 +++++------- indra/newview/llviewermedia.h | 1 + 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 6c04321539..c2087b7c35 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1702,11 +1702,13 @@ void LLViewerMediaImpl::destroyMediaSource() cancelMimeTypeProbe(); + mLock.lock(); // Delay tear-down while bg thread is updating if(mMediaSource) { mMediaSource->setDeleteOK(true) ; mMediaSource = NULL; // shared pointer } + mLock.unlock(); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -2901,16 +2903,11 @@ void LLViewerMediaImpl::update() return; } - // Push update to worker thread auto main_queue = LLMediaTextureUpdateThread::sEnabled ? mMainQueue.lock() : nullptr; ref(); // protect texture from deletion while active on bg queue if (main_queue) { - // replace GL name - //llassert(!mTextureId.isNull()); - //LLImageGL* base_image = LLViewerTextureManager::getMediaTexture(mTextureId)->getGLTexture(); - //GLuint retired_name = base_image->allocNew(); main_queue->postTo( mTexUpdateQueue, // Worker thread queue [this]() // work done on update worker thread @@ -2934,12 +2931,12 @@ void LLViewerMediaImpl::update() void LLViewerMediaImpl::doMediaTexUpdate() { LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; + mLock.lock(); // don't allow media source tear-down during update + LLViewerMediaTexture* media_tex = updateMediaImage(); if (media_tex && mMediaSource) { - llassert(mMediaSource); - LLRect dirty_rect; S32 media_width = mMediaSource->getTextureWidth(); S32 media_height = mMediaSource->getTextureHeight(); @@ -2987,6 +2984,7 @@ void LLViewerMediaImpl::doMediaTexUpdate() mMediaSource->resetDirty(); } } + mLock.unlock(); } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 03a14421ff..0afb2162ab 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -432,6 +432,7 @@ private: private: // a single media url with some data and an impl. boost::shared_ptr mMediaSource; + LLMutex mLock; F64 mZoomFactor; LLUUID mTextureId; bool mMovieImageHasMips; -- cgit v1.2.3 From 19281510bce123bfa85a0ec8f564a7ccb8f31aa9 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Tue, 1 Feb 2022 14:23:06 +0200 Subject: SL-16752 FIXED [Mac] Enabling or disabling vsync does not take effect until the next session. --- indra/newview/llviewercontrol.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index e53f988c6e..4618871630 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -260,9 +260,8 @@ static bool handleAnisotropicChanged(const LLSD& newvalue) static bool handleVSyncChanged(const LLSD& newvalue) { -#if LL_WINDOWS gViewerWindow->getWindow()->toggleVSync(newvalue.asBoolean()); -#endif + return true; } -- cgit v1.2.3 From 0b850360f5f3e520fa3bd321e2e105c24d1f46f0 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 1 Feb 2022 22:28:02 +0000 Subject: SL-16714 and SL-16750 Break rigged alpha into its own pass (restore release like behavior) and fix rigged alpha emissive not rendering. --- indra/newview/lldrawpool.h | 1 + indra/newview/lldrawpoolalpha.cpp | 168 ++++++++++++++++++++++------------- indra/newview/lldrawpoolalpha.h | 4 +- indra/newview/llspatialpartition.cpp | 31 +++++++ indra/newview/llspatialpartition.h | 9 ++ indra/newview/llvovolume.cpp | 2 +- indra/newview/pipeline.cpp | 20 +++++ indra/newview/pipeline.h | 2 + 8 files changed, 171 insertions(+), 66 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index d4f30fc51a..fd1b022e5b 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -183,6 +183,7 @@ public: PASS_GLOW, PASS_GLOW_RIGGED, PASS_ALPHA, + PASS_ALPHA_RIGGED, PASS_ALPHA_MASK, PASS_ALPHA_MASK_RIGGED, PASS_FULLBRIGHT_ALPHA_MASK, // Diffuse texture used as alpha mask and fullbright diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 9da20cc375..963ea6ff8b 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -129,23 +129,26 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass) LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; deferred_render = TRUE; - // first pass, regular forward alpha rendering - { - emissive_shader = (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram; - prepare_alpha_shader(emissive_shader, true, false); - - fullbright_shader = (LLPipeline::sImpostorRender) ? &gDeferredFullbrightProgram : - (LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterProgram : &gDeferredFullbrightProgram; - prepare_alpha_shader(fullbright_shader, true, false); - - simple_shader = (LLPipeline::sImpostorRender) ? &gDeferredAlphaImpostorProgram : - (LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram : &gDeferredAlphaProgram; - prepare_alpha_shader(simple_shader, false, true); //prime simple shader (loads shadow relevant uniforms) - - forwardRender(); - } + // prepare shaders + emissive_shader = (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram; + prepare_alpha_shader(emissive_shader, true, false); + + fullbright_shader = (LLPipeline::sImpostorRender) ? &gDeferredFullbrightProgram : + (LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterProgram : &gDeferredFullbrightProgram; + prepare_alpha_shader(fullbright_shader, true, false); + + simple_shader = (LLPipeline::sImpostorRender) ? &gDeferredAlphaImpostorProgram : + (LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram : &gDeferredAlphaProgram; + prepare_alpha_shader(simple_shader, false, true); //prime simple shader (loads shadow relevant uniforms) + - // second pass, render to depth for depth of field effects + // first pass, render rigged objects only and render to depth buffer + forwardRender(true); + + // second pass, regular forward alpha rendering + forwardRender(); + + // final pass, render to depth for depth of field effects if (!LLPipeline::sImpostorRender && gSavedSettings.getBOOL("RenderDepthOfField")) { //update depth buffer sampler @@ -209,10 +212,14 @@ void LLDrawPoolAlpha::render(S32 pass) prepare_forward_shader(fullbright_shader, minimum_alpha); prepare_forward_shader(simple_shader, minimum_alpha); + //first pass -- rigged only and drawn to depth buffer + forwardRender(true); + + //second pass -- non-rigged, no depth buffer writes forwardRender(); } -void LLDrawPoolAlpha::forwardRender() +void LLDrawPoolAlpha::forwardRender(bool rigged) { gPipeline.enableLightsDynamic(); @@ -221,7 +228,8 @@ void LLDrawPoolAlpha::forwardRender() //enable writing to alpha for emissive effects gGL.setColorMask(true, true); - bool write_depth = LLDrawPoolWater::sSkipScreenCopy + bool write_depth = rigged + || LLDrawPoolWater::sSkipScreenCopy // we want depth written so that rendered alpha will // contribute to the alpha mask used for impostors || LLPipeline::sImpostorRenderAlphaDepthPass; @@ -236,11 +244,17 @@ void LLDrawPoolAlpha::forwardRender() // If the face is more than 90% transparent, then don't update the Depth buffer for Dof // We don't want the nearly invisible objects to cause of DoF effects - renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2); + renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, false, rigged); gGL.setColorMask(true, false); - renderDebugAlpha(); + if (!rigged) + { //render "highlight alpha" on final non-rigged pass + // NOTE -- hacky call here protected by !rigged instead of alongside "forwardRender" + // so renderDebugAlpha is executed while gls_pipeline_alpha and depth GL state + // variables above are still in scope + renderDebugAlpha(); + } } void LLDrawPoolAlpha::renderDebugAlpha() @@ -291,54 +305,60 @@ void LLDrawPoolAlpha::renderDebugAlpha() void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) { - LLVOAvatar* lastAvatar = nullptr; - U64 lastMeshId = 0; + for (int pass = 0; pass < 2; ++pass) + { //two passes, one rigged and one not + LLVOAvatar* lastAvatar = nullptr; + U64 lastMeshId = 0; - for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) - { - LLSpatialGroup* group = *i; - if (group->getSpatialPartition()->mRenderByGroup && - !group->isDead()) - { - LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; + LLCullResult::sg_iterator begin = pass == 0 ? gPipeline.beginAlphaGroups() : gPipeline.beginRiggedAlphaGroups(); + LLCullResult::sg_iterator end = pass == 0 ? gPipeline.endAlphaGroups() : gPipeline.endRiggedAlphaGroups(); - for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) - { - LLDrawInfo& params = **k; - - if (params.mParticle) - { - continue; - } - - bool rigged = (params.mAvatar != nullptr); - gHighlightProgram.bind(rigged); - gGL.diffuseColor4f(1, 0, 0, 1); + for (LLCullResult::sg_iterator i = begin; i != end; ++i) + { + LLSpatialGroup* group = *i; + if (group->getSpatialPartition()->mRenderByGroup && + !group->isDead()) + { + LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA+pass]; // <-- hacky + pass to use PASS_ALPHA_RIGGED on second pass - if (rigged) + for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { - if (lastAvatar != params.mAvatar || - lastMeshId != params.mSkinInfo->mHash) + LLDrawInfo& params = **k; + + if (params.mParticle) { - if (!uploadMatrixPalette(params)) + continue; + } + + bool rigged = (params.mAvatar != nullptr); + gHighlightProgram.bind(rigged); + gGL.diffuseColor4f(1, 0, 0, 1); + + if (rigged) + { + if (lastAvatar != params.mAvatar || + lastMeshId != params.mSkinInfo->mHash) { - continue; + if (!uploadMatrixPalette(params)) + { + continue; + } + lastAvatar = params.mAvatar; + lastMeshId = params.mSkinInfo->mHash; } - lastAvatar = params.mAvatar; - lastMeshId = params.mSkinInfo->mHash; } - } - LLRenderPass::applyModelMatrix(params); - if (params.mGroup) - { - params.mGroup->rebuildMesh(); - } - params.mVertexBuffer->setBufferFast(rigged ? mask | LLVertexBuffer::MAP_WEIGHT4 : mask); - params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); - } - } - } + LLRenderPass::applyModelMatrix(params); + if (params.mGroup) + { + params.mGroup->rebuildMesh(); + } + params.mVertexBuffer->setBufferFast(rigged ? mask | LLVertexBuffer::MAP_WEIGHT4 : mask); + params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); + } + } + } + } // make sure static version of highlight shader is bound before returning gHighlightProgram.bind(); @@ -471,6 +491,8 @@ void LLDrawPoolAlpha::renderRiggedEmissives(U32 mask, std::vector& LLVOAvatar* lastAvatar = nullptr; U64 lastMeshId = 0; + mask |= LLVertexBuffer::MAP_WEIGHT4; + for (LLDrawInfo* draw : emissives) { bool tex_setup = TexSetup(draw, false); @@ -488,7 +510,7 @@ void LLDrawPoolAlpha::renderRiggedEmissives(U32 mask, std::vector& } } -void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only) +void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; BOOL initialized_lighting = FALSE; @@ -498,7 +520,21 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only) U64 lastMeshId = 0; LLGLSLShader* lastAvatarShader = nullptr; - for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) + LLCullResult::sg_iterator begin; + LLCullResult::sg_iterator end; + + if (rigged) + { + begin = gPipeline.beginRiggedAlphaGroups(); + end = gPipeline.endRiggedAlphaGroups(); + } + else + { + begin = gPipeline.beginAlphaGroups(); + end = gPipeline.endAlphaGroups(); + } + + for (LLCullResult::sg_iterator i = begin; i != end; ++i) { LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("renderAlpha - group"); LLSpatialGroup* group = *i; @@ -521,12 +557,18 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only) bool disable_cull = is_particle_or_hud_particle; LLGLDisable cull(disable_cull ? GL_CULL_FACE : 0); - LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; + LLSpatialGroup::drawmap_elem_t& draw_info = rigged ? group->mDrawMap[LLRenderPass::PASS_ALPHA_RIGGED] : group->mDrawMap[LLRenderPass::PASS_ALPHA]; for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { - LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("ra - push batch") LLDrawInfo& params = **k; + if ((bool)params.mAvatar != rigged) + { + continue; + } + + LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("ra - push batch") + U32 have_mask = params.mVertexBuffer->getTypeMask() & mask; if (have_mask != mask) { //FIXME! diff --git a/indra/newview/lldrawpoolalpha.h b/indra/newview/lldrawpoolalpha.h index 1f6909e282..fa8ef0f227 100644 --- a/indra/newview/lldrawpoolalpha.h +++ b/indra/newview/lldrawpoolalpha.h @@ -55,13 +55,13 @@ public: /*virtual*/ S32 getNumPasses() { return 1; } virtual void render(S32 pass = 0); - void forwardRender(); + void forwardRender(bool write_depth = false); /*virtual*/ void prerender(); void renderDebugAlpha(); void renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE); - void renderAlpha(U32 mask, bool depth_only = false); + void renderAlpha(U32 mask, bool depth_only = false, bool rigged = false); void renderAlphaHighlight(U32 mask); bool uploadMatrixPalette(const LLDrawInfo& params); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index eaf6186dae..5c648c11e1 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -4022,6 +4022,7 @@ LLCullResult::LLCullResult() { mVisibleGroupsAllocated = 0; mAlphaGroupsAllocated = 0; + mRiggedAlphaGroupsAllocated = 0; mOcclusionGroupsAllocated = 0; mDrawableGroupsAllocated = 0; mVisibleListAllocated = 0; @@ -4033,6 +4034,9 @@ LLCullResult::LLCullResult() mAlphaGroups.clear(); mAlphaGroups.push_back(NULL); mAlphaGroupsEnd = &mAlphaGroups[0]; + mRiggedAlphaGroups.clear(); + mRiggedAlphaGroups.push_back(NULL); + mRiggedAlphaGroupsEnd = &mRiggedAlphaGroups[0]; mOcclusionGroups.clear(); mOcclusionGroups.push_back(NULL); mOcclusionGroupsEnd = &mOcclusionGroups[0]; @@ -4073,6 +4077,9 @@ void LLCullResult::clear() mAlphaGroupsSize = 0; mAlphaGroupsEnd = &mAlphaGroups[0]; + mRiggedAlphaGroupsSize = 0; + mRiggedAlphaGroupsEnd = &mRiggedAlphaGroups[0]; + mOcclusionGroupsSize = 0; mOcclusionGroupsEnd = &mOcclusionGroups[0]; @@ -4117,6 +4124,16 @@ LLCullResult::sg_iterator LLCullResult::endAlphaGroups() return mAlphaGroupsEnd; } +LLCullResult::sg_iterator LLCullResult::beginRiggedAlphaGroups() +{ + return &mRiggedAlphaGroups[0]; +} + +LLCullResult::sg_iterator LLCullResult::endRiggedAlphaGroups() +{ + return mRiggedAlphaGroupsEnd; +} + LLCullResult::sg_iterator LLCullResult::beginOcclusionGroups() { return &mOcclusionGroups[0]; @@ -4195,6 +4212,20 @@ void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) mAlphaGroupsEnd = &mAlphaGroups[mAlphaGroupsSize]; } +void LLCullResult::pushRiggedAlphaGroup(LLSpatialGroup* group) +{ + if (mRiggedAlphaGroupsSize < mRiggedAlphaGroupsAllocated) + { + mRiggedAlphaGroups[mRiggedAlphaGroupsSize] = group; + } + else + { + pushBack(mRiggedAlphaGroups, mRiggedAlphaGroupsAllocated, group); + } + ++mRiggedAlphaGroupsSize; + mRiggedAlphaGroupsEnd = &mRiggedAlphaGroups[mRiggedAlphaGroupsSize]; +} + void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) { if (mOcclusionGroupsSize < mOcclusionGroupsAllocated) diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index afe24d7d1f..eefb5b0eba 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -470,6 +470,9 @@ public: sg_iterator beginAlphaGroups(); sg_iterator endAlphaGroups(); + sg_iterator beginRiggedAlphaGroups(); + sg_iterator endRiggedAlphaGroups(); + bool hasOcclusionGroups() { return mOcclusionGroupsSize > 0; } sg_iterator beginOcclusionGroups(); sg_iterator endOcclusionGroups(); @@ -488,6 +491,7 @@ public: void pushVisibleGroup(LLSpatialGroup* group); void pushAlphaGroup(LLSpatialGroup* group); + void pushRiggedAlphaGroup(LLSpatialGroup* group); void pushOcclusionGroup(LLSpatialGroup* group); void pushDrawableGroup(LLSpatialGroup* group); void pushDrawable(LLDrawable* drawable); @@ -496,6 +500,7 @@ public: U32 getVisibleGroupsSize() { return mVisibleGroupsSize; } U32 getAlphaGroupsSize() { return mAlphaGroupsSize; } + U32 getRiggedAlphaGroupsSize() { return mRiggedAlphaGroupsSize; } U32 getDrawableGroupsSize() { return mDrawableGroupsSize; } U32 getVisibleListSize() { return mVisibleListSize; } U32 getVisibleBridgeSize() { return mVisibleBridgeSize; } @@ -509,6 +514,7 @@ private: U32 mVisibleGroupsSize; U32 mAlphaGroupsSize; + U32 mRiggedAlphaGroupsSize; U32 mOcclusionGroupsSize; U32 mDrawableGroupsSize; U32 mVisibleListSize; @@ -516,6 +522,7 @@ private: U32 mVisibleGroupsAllocated; U32 mAlphaGroupsAllocated; + U32 mRiggedAlphaGroupsAllocated; U32 mOcclusionGroupsAllocated; U32 mDrawableGroupsAllocated; U32 mVisibleListAllocated; @@ -527,6 +534,8 @@ private: sg_iterator mVisibleGroupsEnd; sg_list_t mAlphaGroups; sg_iterator mAlphaGroupsEnd; + sg_list_t mRiggedAlphaGroups; + sg_iterator mRiggedAlphaGroupsEnd; sg_list_t mOcclusionGroups; sg_iterator mOcclusionGroupsEnd; sg_list_t mDrawableGroups; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 8bc570311c..a60bece037 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5143,7 +5143,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, bool rigged = facep->isState(LLFace::RIGGED); - if (rigged && type != LLRenderPass::PASS_ALPHA) + if (rigged) { // hacky, should probably clean up -- if this face is rigged, put it in "type + 1" // See LLRenderPass PASS_foo enum diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 117766afea..8d45e64bf8 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -3822,6 +3822,16 @@ void LLPipeline::postSort(LLCamera& camera) sCull->pushAlphaGroup(group); } } + + LLSpatialGroup::draw_map_t::iterator rigged_alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA_RIGGED); + + if (rigged_alpha != group->mDrawMap.end()) + { //store rigged alpha groups for LLDrawPoolAlpha prepass (skip distance update, rigged attachments use depth buffer) + if (hasRenderType(LLDrawPool::POOL_ALPHA)) + { + sCull->pushRiggedAlphaGroup(group); + } + } } } @@ -11153,6 +11163,16 @@ LLCullResult::sg_iterator LLPipeline::endAlphaGroups() return sCull->endAlphaGroups(); } +LLCullResult::sg_iterator LLPipeline::beginRiggedAlphaGroups() +{ + return sCull->beginRiggedAlphaGroups(); +} + +LLCullResult::sg_iterator LLPipeline::endRiggedAlphaGroups() +{ + return sCull->endRiggedAlphaGroups(); +} + bool LLPipeline::hasRenderType(const U32 type) const { // STORM-365 : LLViewerJointAttachment::setAttachmentVisibility() is setting type to 0 to actually mean "do not render" diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index fdc3738472..6114aa4f6c 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -338,6 +338,8 @@ public: LLCullResult::drawinfo_iterator endRenderMap(U32 type); LLCullResult::sg_iterator beginAlphaGroups(); LLCullResult::sg_iterator endAlphaGroups(); + LLCullResult::sg_iterator beginRiggedAlphaGroups(); + LLCullResult::sg_iterator endRiggedAlphaGroups(); void addTrianglesDrawn(S32 index_count, U32 render_type = LLRender::TRIANGLES); -- cgit v1.2.3 From 795a349b9f44183970b1e8abc632c4d7f8bbea37 Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Tue, 1 Feb 2022 15:44:09 -0700 Subject: Revert "Merged in euclid-16418-a (pull request #852)" This reverts commit dcf8f695367a1bcc9c495ea93a89927dd83802af, reversing changes made to 594910a8408f67f1af7c66d5a4dfde3626669245. --- indra/newview/llviewermedia.cpp | 12 +++++++----- indra/newview/llviewermedia.h | 1 - 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index c2087b7c35..6c04321539 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1702,13 +1702,11 @@ void LLViewerMediaImpl::destroyMediaSource() cancelMimeTypeProbe(); - mLock.lock(); // Delay tear-down while bg thread is updating if(mMediaSource) { mMediaSource->setDeleteOK(true) ; mMediaSource = NULL; // shared pointer } - mLock.unlock(); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -2903,11 +2901,16 @@ void LLViewerMediaImpl::update() return; } + // Push update to worker thread auto main_queue = LLMediaTextureUpdateThread::sEnabled ? mMainQueue.lock() : nullptr; ref(); // protect texture from deletion while active on bg queue if (main_queue) { + // replace GL name + //llassert(!mTextureId.isNull()); + //LLImageGL* base_image = LLViewerTextureManager::getMediaTexture(mTextureId)->getGLTexture(); + //GLuint retired_name = base_image->allocNew(); main_queue->postTo( mTexUpdateQueue, // Worker thread queue [this]() // work done on update worker thread @@ -2931,12 +2934,12 @@ void LLViewerMediaImpl::update() void LLViewerMediaImpl::doMediaTexUpdate() { LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; - mLock.lock(); // don't allow media source tear-down during update - LLViewerMediaTexture* media_tex = updateMediaImage(); if (media_tex && mMediaSource) { + llassert(mMediaSource); + LLRect dirty_rect; S32 media_width = mMediaSource->getTextureWidth(); S32 media_height = mMediaSource->getTextureHeight(); @@ -2984,7 +2987,6 @@ void LLViewerMediaImpl::doMediaTexUpdate() mMediaSource->resetDirty(); } } - mLock.unlock(); } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 0afb2162ab..03a14421ff 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -432,7 +432,6 @@ private: private: // a single media url with some data and an impl. boost::shared_ptr mMediaSource; - LLMutex mLock; F64 mZoomFactor; LLUUID mTextureId; bool mMovieImageHasMips; -- cgit v1.2.3 From fdc4a81b578f26ce573d6b60760c8235312a6372 Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Tue, 1 Feb 2022 15:49:32 -0700 Subject: Revert "Merged in euclid-16418 (pull request #846)" This reverts commit 40fe5277e1390c975d9a3184ff8fc46d69dfb450, reversing changes made to af830e5fc5840194be95140f644a27011b9b7e06. --- indra/llimage/llimage.cpp | 96 ++++----- indra/llrender/llimagegl.cpp | 66 +----- indra/llrender/llimagegl.h | 10 +- indra/newview/llviewermedia.cpp | 427 ++++++++++++++------------------------ indra/newview/llviewermedia.h | 37 +--- indra/newview/llviewertexture.cpp | 2 +- indra/newview/llviewerwindow.cpp | 6 +- 7 files changed, 214 insertions(+), 430 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index ba7ee0b465..15b07e5318 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -925,73 +925,47 @@ bool LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height, void LLImageRaw::clear(U8 r, U8 g, U8 b, U8 a) { - LL_PROFILE_ZONE_SCOPED; - S8 components = getComponents(); - llassert( components > 0 && components <= 4 ); - - // This is fairly bogus, but it'll do for now. - if (isBufferInvalid()) - { - LL_WARNS() << "Invalid image buffer" << LL_ENDL; - return; - } + llassert( getComponents() <= 4 ); + // This is fairly bogus, but it'll do for now. + if (isBufferInvalid()) + { + LL_WARNS() << "Invalid image buffer" << LL_ENDL; + return; + } - switch (components) - { - case 1: - { - U8 *dst = getData(); - S32 count = getWidth() * getHeight(); - llassert(count == getDataSize()); - std::fill_n(dst, count, r); - break; - } - case 2: - { - U16 *dst = (U16 *)getData(); - S32 count = getWidth() * getHeight(); - llassert(count == getDataSize() / 2); -#ifdef LL_LITTLE_ENDIAN - U16 val = (U16)(r | g << 8); -#else - U16 val = (U16)(r << 8 | g); -#endif - std::fill_n(dst, count, val); - break; - } - case 3: - { - U8 *dst = getData(); - S32 count = getWidth() * getHeight(); - llassert(count == getDataSize() / 3); - for (S32 i = 0; i < count; i++) - { - *dst++ = r; - *dst++ = g; - *dst++ = b; - } - break; - } - case 4: - { - U32 *dst = (U32 *)getData(); - S32 count = getWidth() * getHeight(); - llassert(count == getDataSize() / 4); -#ifdef LL_LITTLE_ENDIAN - U32 val = (U32)(r | g << 8 | b << 16 | a << 24); -#else - U32 val = (U32)(r << 24 | g << 16 | b << 8 | a); -#endif - std::fill_n(dst, count, val); - break; - } - } + U8 *pos = getData(); + U32 x, y; + for (x = 0; x < getWidth(); x++) + { + for (y = 0; y < getHeight(); y++) + { + *pos = r; + pos++; + if (getComponents() == 1) + { + continue; + } + *pos = g; + pos++; + if (getComponents() == 2) + { + continue; + } + *pos = b; + pos++; + if (getComponents() == 3) + { + continue; + } + *pos = a; + pos++; + } + } } // Reverses the order of the rows in the image void LLImageRaw::verticalFlip() { - LL_PROFILE_ZONE_SCOPED; S32 row_bytes = getWidth() * getComponents(); llassert(row_bytes > 0); std::vector line_buffer(row_bytes); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 4b4f071171..1e9b9f642e 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1215,8 +1215,9 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE) { //GL_ALPHA is deprecated, convert to RGBA use_scratch = true; + scratch = new U32[width * height]; + U32 pixel_count = (U32)(width * height); - scratch = new U32[pixel_count]; for (U32 i = 0; i < pixel_count; i++) { U8* pix = (U8*)&scratch[i]; @@ -1231,8 +1232,9 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE) { //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA use_scratch = true; + scratch = new U32[width * height]; + U32 pixel_count = (U32)(width * height); - scratch = new U32[pixel_count]; for (U32 i = 0; i < pixel_count; i++) { U8 lum = ((U8*)pixels)[i * 2 + 0]; @@ -1250,8 +1252,9 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE) { //GL_LUMINANCE_ALPHA is deprecated, convert to RGB use_scratch = true; + scratch = new U32[width * height]; + U32 pixel_count = (U32)(width * height); - scratch = new U32[pixel_count]; for (U32 i = 0; i < pixel_count; i++) { U8 lum = ((U8*)pixels)[i]; @@ -1311,7 +1314,10 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt } stop_glerror(); - if (scratch) delete[] scratch; + if (use_scratch) + { + delete[] scratch; + } } //create an empty GL texture: just create a texture name @@ -1465,49 +1471,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S return createGLTexture(discard_level, rawdata, FALSE, usename); } -// Create a new GL name and allocate tex storage (unitialized) for it -// Used to break resource contention stall in background media tex updates -void LLImageGL::allocNewTexName() -{ - LL_PROFILE_ZONE_SCOPED; - if (on_main_thread()) return; // Should only be called on bg update thread - if (!mGLTextureCreated) return; - if (0 != mNewTexName) return; // only 1 rename in flight at a time - - generateTextures(1, &mNewTexName); // create new GL name - - mHasMipMaps = false; // Media textures aren't mipped - mMipLevels = 0; - // Set state to match current - gGL.getTexUnit(0)->bind(this, false, false, mNewTexName); - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel); - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_WIDTH, mWidth); - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_HEIGHT, mHeight); - gGL.getTexUnit(0)->setHasMipMaps(mHasMipMaps); - gGL.getTexUnit(0)->setTextureAddressMode(mAddressMode); - gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption); - - setManualImage(mTarget, 0, mFormatInternal, mWidth, mHeight, mFormatPrimary, mFormatType, - (GLvoid *) nullptr, mAllowCompression); - - gGL.getTexUnit(0)->unbind(mBindTarget); - - mLastBindTime = sLastFrameTime; -} - -// Delete no-longer-needed GL tex name (on main thread) -void LLImageGL::swapTexName() -{ - if (mNewTexName) - { - deleteTextures(1, &mTexName); - mTexName = mNewTexName; - mNewTexName = 0; - } -} - -BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips /* = FALSE */, S32 usename /* = 0 */) +BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; checkActiveThread(); @@ -1751,14 +1715,6 @@ void LLImageGL::destroyGLTexture() mTexName = 0; mGLTextureCreated = FALSE ; } - - // clean up any in-flight name change - if (0 != mNewTexName) - { - // Memory is transient, not tracked by sGlobalTextuerMemory - LLImageGL::deleteTextures(1, &mNewTexName); - mNewTexName = 0; - } } //force to invalidate the gl texture, most likely a sculpty texture diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index f311170823..d6f4b13a51 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -109,17 +109,15 @@ public: static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression = true); BOOL createGLTexture() ; - BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = sMaxCategories-1); + BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, + S32 category = sMaxCategories-1); BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0); - void setImage(const LLImageRaw* imageraw); + void setImage(const LLImageRaw* imageraw); BOOL setImage(const U8* data_in, BOOL data_hasmips = FALSE, S32 usename = 0); BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height); - - void allocNewTexName(); - void swapTexName(); - + // Read back a raw image for this discard level, if it exists BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const; void destroyGLTexture(); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 6c04321539..63f57e81cc 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -39,7 +39,6 @@ #include "llfilepicker.h" #include "llfloaterwebcontent.h" // for handling window close requests and geometry change requests in media browser windows. #include "llfocusmgr.h" -#include "llimagegl.h" #include "llkeyboard.h" #include "lllogininstance.h" #include "llmarketplacefunctions.h" @@ -79,9 +78,6 @@ #include // for SkinFolder listener #include -// Statics -bool LLMediaTextureUpdateThread::sEnabled = false; - class LLMediaFilePicker : public LLFilePickerThread // deletes itself when done { public: @@ -639,7 +635,6 @@ static bool proximity_comparitor(const LLViewerMediaImpl* i1, const LLViewerMedi static LLTrace::BlockTimerStatHandle FTM_MEDIA_UPDATE("Update Media"); static LLTrace::BlockTimerStatHandle FTM_MEDIA_SPARE_IDLE("Spare Idle"); static LLTrace::BlockTimerStatHandle FTM_MEDIA_UPDATE_INTEREST("Update/Interest"); -static LLTrace::BlockTimerStatHandle FTM_MEDIA_UPDATE_VOLUME("Update/Volume"); static LLTrace::BlockTimerStatHandle FTM_MEDIA_SORT("Media Sort"); static LLTrace::BlockTimerStatHandle FTM_MEDIA_SORT2("Media Sort 2"); static LLTrace::BlockTimerStatHandle FTM_MEDIA_MISC("Misc"); @@ -1595,8 +1590,6 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, media_tex->setMediaImpl(); } - mMainQueue = LL::WorkQueue::getInstance("mainloop"); - mTexUpdateQueue = LL::WorkQueue::getInstance("LLMediaTextureUpdate"); // Share work queue with tex loader. } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1610,25 +1603,6 @@ LLViewerMediaImpl::~LLViewerMediaImpl() remove_media_impl(this); } -////////////////////////////////////////////////////////////////////////////////////////// -//static -void LLViewerMediaImpl::initClass(LLWindow* window, bool multi_threaded /* = false */) -{ - LL_PROFILE_ZONE_SCOPED; - if (multi_threaded) - { - LLMediaTextureUpdateThread::createInstance(window); - } -} - -////////////////////////////////////////////////////////////////////////////////////////// -//static -void LLViewerMediaImpl::cleanupClass() -{ - LL_PROFILE_ZONE_SCOPED; - LLMediaTextureUpdateThread::deleteSingleton(); -} - ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::emitEvent(LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event) { @@ -2113,7 +2087,6 @@ void LLViewerMediaImpl::setMute(bool mute) ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::updateVolume() { - LL_RECORD_BLOCK_TIME(FTM_MEDIA_UPDATE_VOLUME); if(mMediaSource) { // always scale the volume by the global media volume @@ -2826,252 +2799,199 @@ static LLTrace::BlockTimerStatHandle FTM_MEDIA_SET_SUBIMAGE("Set Subimage"); void LLViewerMediaImpl::update() { LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; //LL_RECORD_BLOCK_TIME(FTM_MEDIA_DO_UPDATE); - if(mMediaSource == NULL) - { - if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED) - { - // This media source should not be loaded. - } - else if(mPriority <= LLPluginClassMedia::PRIORITY_SLIDESHOW) - { - // Don't load new instances that are at PRIORITY_SLIDESHOW or below. They're just kept around to preserve state. - } + if(mMediaSource == NULL) + { + if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED) + { + // This media source should not be loaded. + } + else if(mPriority <= LLPluginClassMedia::PRIORITY_SLIDESHOW) + { + // Don't load new instances that are at PRIORITY_SLIDESHOW or below. They're just kept around to preserve state. + } else if (!mMimeProbe.expired()) - { - // this media source is doing a MIME type probe -- don't try loading it again. - } - else - { - // This media may need to be loaded. - if(sMediaCreateTimer.hasExpired()) - { - LL_DEBUGS("PluginPriority") << this << ": creating media based on timer expiration" << LL_ENDL; - createMediaSource(); - sMediaCreateTimer.setTimerExpirySec(LLVIEWERMEDIA_CREATE_DELAY); - } - else - { - LL_DEBUGS("PluginPriority") << this << ": NOT creating media (waiting on timer)" << LL_ENDL; - } - } - } - else - { - updateVolume(); + { + // this media source is doing a MIME type probe -- don't try loading it again. + } + else + { + // This media may need to be loaded. + if(sMediaCreateTimer.hasExpired()) + { + LL_DEBUGS("PluginPriority") << this << ": creating media based on timer expiration" << LL_ENDL; + createMediaSource(); + sMediaCreateTimer.setTimerExpirySec(LLVIEWERMEDIA_CREATE_DELAY); + } + else + { + LL_DEBUGS("PluginPriority") << this << ": NOT creating media (waiting on timer)" << LL_ENDL; + } + } + } + else + { + updateVolume(); - // TODO: this is updated every frame - is this bad? - // Removing this as part of the post viewer64 media update - // Removed as not implemented in CEF embedded browser - // See MAINT-8194 for a more fuller description - // updateJavascriptObject(); - } + // TODO: this is updated every frame - is this bad? + // Removing this as part of the post viewer64 media update + // Removed as not implemented in CEF embedded browser + // See MAINT-8194 for a more fuller description + // updateJavascriptObject(); + } - if(mMediaSource == NULL) - { - return; - } + if(mMediaSource == NULL) + { + return; + } - // Make sure a navigate doesn't happen during the idle -- it can cause mMediaSource to get destroyed, which can cause a crash. - setNavigateSuspended(true); + // Make sure a navigate doesn't happen during the idle -- it can cause mMediaSource to get destroyed, which can cause a crash. + setNavigateSuspended(true); - mMediaSource->idle(); + mMediaSource->idle(); - setNavigateSuspended(false); + setNavigateSuspended(false); - if(mMediaSource == NULL) - { - return; - } + if(mMediaSource == NULL) + { + return; + } - if(mMediaSource->isPluginExited()) - { - resetPreviousMediaState(); - destroyMediaSource(); - return; - } + if(mMediaSource->isPluginExited()) + { + resetPreviousMediaState(); + destroyMediaSource(); + return; + } - if(!mMediaSource->textureValid()) - { - return; - } + if(!mMediaSource->textureValid()) + { + return; + } - if(mSuspendUpdates || !mVisible) - { - return; - } + if(mSuspendUpdates || !mVisible) + { + return; + } + LLViewerMediaTexture* placeholder_image = updatePlaceholderImage(); - // Push update to worker thread - auto main_queue = LLMediaTextureUpdateThread::sEnabled ? mMainQueue.lock() : nullptr; - ref(); // protect texture from deletion while active on bg queue - if (main_queue) - { - // replace GL name - //llassert(!mTextureId.isNull()); - //LLImageGL* base_image = LLViewerTextureManager::getMediaTexture(mTextureId)->getGLTexture(); - //GLuint retired_name = base_image->allocNew(); - main_queue->postTo( - mTexUpdateQueue, // Worker thread queue - [this]() // work done on update worker thread - { - doMediaTexUpdate(); - }, - [this]() // callback to main thread - { - endMediaTexUpdate(); - unref(); - }); - } - else - { - doMediaTexUpdate(); // otherwise, update on main thread - unref(); - } -} + if(placeholder_image) + { + LLRect dirty_rect; -////////////////////////////////////////////////////////////////////////////////////////// -void LLViewerMediaImpl::doMediaTexUpdate() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; - LLViewerMediaTexture* media_tex = updateMediaImage(); + // Since we're updating this texture, we know it's playing. Tell the texture to do its replacement magic so it gets rendered. + placeholder_image->setPlaying(TRUE); - if (media_tex && mMediaSource) - { - llassert(mMediaSource); - - LLRect dirty_rect; - S32 media_width = mMediaSource->getTextureWidth(); - S32 media_height = mMediaSource->getTextureHeight(); - S32 media_depth = mMediaSource->getTextureDepth(); + if(mMediaSource->getDirty(&dirty_rect)) + { + // Constrain the dirty rect to be inside the texture + S32 x_pos = llmax(dirty_rect.mLeft, 0); + S32 y_pos = llmax(dirty_rect.mBottom, 0); + S32 width = llmin(dirty_rect.mRight, placeholder_image->getWidth()) - x_pos; + S32 height = llmin(dirty_rect.mTop, placeholder_image->getHeight()) - y_pos; - // Since we're updating this texture, we know it's playing. Tell the texture to do its replacement magic so it gets rendered. - media_tex->setPlaying(TRUE); + if(width > 0 && height > 0) + { - if (mMediaSource->getDirty(&dirty_rect)) - { - // Constrain the dirty rect to be inside the texture - S32 x_pos = llmax(dirty_rect.mLeft, 0); - S32 y_pos = llmax(dirty_rect.mBottom, 0); - S32 width = llmin(dirty_rect.mRight, media_width) - x_pos; - S32 height = llmin(dirty_rect.mTop, media_height) - y_pos; + U8* data = NULL; + { + LL_PROFILE_ZONE_NAMED_CATEGORY_MEDIA("media get data"); //LL_RECORD_BLOCK_TIME(FTM_MEDIA_GET_DATA); + data = mMediaSource->getBitsData(); + } - if (width > 0 && height > 0) - { - U8* data = NULL; - S32 data_width = mMediaSource->getBitsWidth(); - S32 data_height = mMediaSource->getBitsHeight(); - data = mMediaSource->getBitsData(); + if(data != NULL) + { + // Offset the pixels pointer to match x_pos and y_pos + data += ( x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth() ); + data += ( y_pos * mMediaSource->getTextureDepth() ); - if (data != NULL) - { - // Offset the pixels pointer to match x_pos and y_pos - data += (x_pos * media_depth * data_width); - data += (y_pos * media_depth); - - { - LL_PROFILE_ZONE_NAMED_CATEGORY_MEDIA("media set subimage"); //LL_RECORD_BLOCK_TIME(FTM_MEDIA_SET_SUBIMAGE); - media_tex->setSubImage( - data, - data_width, - data_height, - x_pos, - y_pos, - width, - height); - } - } + { + LL_PROFILE_ZONE_NAMED_CATEGORY_MEDIA("media set subimage"); //LL_RECORD_BLOCK_TIME(FTM_MEDIA_SET_SUBIMAGE); + placeholder_image->setSubImage( + data, + mMediaSource->getBitsWidth(), + mMediaSource->getBitsHeight(), + x_pos, + y_pos, + width, + height); + } + } - } + } - mMediaSource->resetDirty(); - } - } + mMediaSource->resetDirty(); + } + } } -////////////////////////////////////////////////////////////////////////////////////////// -// runs on main thread, but only called when bg thread updates are active -void LLViewerMediaImpl::endMediaTexUpdate() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; - LLViewerMediaTexture* base_image = LLViewerTextureManager::findMediaTexture(mTextureId); - llassert(base_image); - - LLImageGL* image = base_image->getGLTexture(); - image->swapTexName(); // retire old GL name -} ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::updateImagesMediaStreams() { } + ////////////////////////////////////////////////////////////////////////////////////////// -LLViewerMediaTexture* LLViewerMediaImpl::updateMediaImage() +LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; - if (!mMediaSource) - { - return nullptr; // not ready for updating - } + if(mTextureId.isNull()) + { + // The code that created this instance will read from the plugin's bits. + return NULL; + } - llassert(!mTextureId.isNull()); - LLViewerMediaTexture* media_tex = LLViewerTextureManager::getMediaTexture( mTextureId ); - - // if on bg thread, create new GL tex image resource to avoid resource contention - if (!on_main_thread()) - { - LLImageGL* image = media_tex->getGLTexture(); - image->allocNewTexName(); - } + LLViewerMediaTexture* placeholder_image = LLViewerTextureManager::getMediaTexture( mTextureId ); - if ( mNeedsNewTexture - || media_tex->getUseMipMaps() - || (media_tex->getWidth() != mMediaSource->getTextureWidth()) - || (media_tex->getHeight() != mMediaSource->getTextureHeight()) - || (mTextureUsedWidth != mMediaSource->getWidth()) - || (mTextureUsedHeight != mMediaSource->getHeight()) - ) - { - LL_DEBUGS("Media") << "initializing media placeholder" << LL_ENDL; - LL_DEBUGS("Media") << "movie image id " << mTextureId << LL_ENDL; - - int texture_width = mMediaSource->getTextureWidth(); - int texture_height = mMediaSource->getTextureHeight(); - int texture_depth = mMediaSource->getTextureDepth(); - - // MEDIAOPT: check to see if size actually changed before doing work - media_tex->destroyGLTexture(); - // MEDIAOPT: apparently just calling setUseMipMaps(FALSE) doesn't work? - media_tex->reinit(FALSE); // probably not needed - - // MEDIAOPT: seems insane that we actually have to make an imageraw then - // immediately discard it - LLPointer raw = new LLImageRaw(texture_width, texture_height, texture_depth); - // Clear the texture to the background color, ignoring alpha. - // convert background color channels from [0.0, 1.0] to [0, 255]; - raw->clear(int(mBackgroundColor.mV[VX] * 255.0f), int(mBackgroundColor.mV[VY] * 255.0f), int(mBackgroundColor.mV[VZ] * 255.0f), 0xff); - - // ask media source for correct GL image format constants - media_tex->setExplicitFormat(mMediaSource->getTextureFormatInternal(), - mMediaSource->getTextureFormatPrimary(), - mMediaSource->getTextureFormatType(), - mMediaSource->getTextureFormatSwapBytes()); - - int discard_level = 0; - media_tex->createGLTexture(discard_level, raw); - - // MEDIAOPT: set this dynamically on play/stop - // FIXME -// media_tex->mIsMediaTexture = true; - mNeedsNewTexture = false; - - // If the amount of the texture being drawn by the media goes down in either width or height, - // recreate the texture to avoid leaving parts of the old image behind. - mTextureUsedWidth = mMediaSource->getWidth(); - mTextureUsedHeight = mMediaSource->getHeight(); - } - return media_tex; + if (mNeedsNewTexture + || placeholder_image->getUseMipMaps() + || (placeholder_image->getWidth() != mMediaSource->getTextureWidth()) + || (placeholder_image->getHeight() != mMediaSource->getTextureHeight()) + || (mTextureUsedWidth != mMediaSource->getWidth()) + || (mTextureUsedHeight != mMediaSource->getHeight()) + ) + { + LL_DEBUGS("Media") << "initializing media placeholder" << LL_ENDL; + LL_DEBUGS("Media") << "movie image id " << mTextureId << LL_ENDL; + + int texture_width = mMediaSource->getTextureWidth(); + int texture_height = mMediaSource->getTextureHeight(); + int texture_depth = mMediaSource->getTextureDepth(); + + // MEDIAOPT: check to see if size actually changed before doing work + placeholder_image->destroyGLTexture(); + // MEDIAOPT: apparently just calling setUseMipMaps(FALSE) doesn't work? + placeholder_image->reinit(FALSE); // probably not needed + + // MEDIAOPT: seems insane that we actually have to make an imageraw then + // immediately discard it + LLPointer raw = new LLImageRaw(texture_width, texture_height, texture_depth); + // Clear the texture to the background color, ignoring alpha. + // convert background color channels from [0.0, 1.0] to [0, 255]; + raw->clear(int(mBackgroundColor.mV[VX] * 255.0f), int(mBackgroundColor.mV[VY] * 255.0f), int(mBackgroundColor.mV[VZ] * 255.0f), 0xff); + int discard_level = 0; + + // ask media source for correct GL image format constants + placeholder_image->setExplicitFormat(mMediaSource->getTextureFormatInternal(), + mMediaSource->getTextureFormatPrimary(), + mMediaSource->getTextureFormatType(), + mMediaSource->getTextureFormatSwapBytes()); + + placeholder_image->createGLTexture(discard_level, raw); + + // MEDIAOPT: set this dynamically on play/stop + // FIXME +// placeholder_image->mIsMediaTexture = true; + mNeedsNewTexture = false; + + // If the amount of the texture being drawn by the media goes down in either width or height, + // recreate the texture to avoid leaving parts of the old image behind. + mTextureUsedWidth = mMediaSource->getWidth(); + mTextureUsedHeight = mMediaSource->getHeight(); + } + + return placeholder_image; } @@ -4000,30 +3920,3 @@ bool LLViewerMediaImpl::isObjectInAgentParcel(LLVOVolume *obj) { return (LLViewerParcelMgr::getInstance()->inAgentParcel(obj->getPositionGlobal())); } - -LLMediaTextureUpdateThread::LLMediaTextureUpdateThread(LLWindow* window) -// We want exactly one thread, of moderate capacity: there are likely only a handful -// of media texture frames in-flight at any one time - : ThreadPool("LLMediaTextureUpdate", 1, 4096) - , mWindow(window) -{ - LL_PROFILE_ZONE_SCOPED; - sEnabled = true; - mFinished = false; - - mContext = mWindow->createSharedContext(); - ThreadPool::start(); -} - -void LLMediaTextureUpdateThread::run() -{ - LL_PROFILE_ZONE_SCOPED; - // We must perform setup on this thread before actually servicing our - // WorkQueue, likewise cleanup afterwards. - mWindow->makeContextCurrent(mContext); - gGL.init(); - ThreadPool::run(); - LLMediaTextureUpdateThread::sEnabled = false; - gGL.shutdown(); - mWindow->destroySharedContext(mContext); -} diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 03a14421ff..71cec5125d 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -197,10 +197,7 @@ public: U8 media_loop); ~LLViewerMediaImpl(); - - static void initClass(LLWindow* window, bool multi_threaded = false); - static void cleanupClass(); - + // Override inherited version from LLViewerMediaEventEmitter virtual void emitEvent(LLPluginClassMedia* self, LLViewerMediaObserver::EMediaEvent event); @@ -269,8 +266,6 @@ public: void scaleTextureCoords(const LLVector2& texture_coords, S32 *x, S32 *y); void update(); - void doMediaTexUpdate(); - void endMediaTexUpdate(); void updateImagesMediaStreams(); LLUUID getMediaTextureID() const; @@ -494,35 +489,7 @@ private: bool mCanceling; private: - LLViewerMediaTexture *updateMediaImage(); - LL::WorkQueue::weak_t mMainQueue; - LL::WorkQueue::weak_t mTexUpdateQueue; - -}; - -// Define a worker thread pool for media updates (ref LLImageGLThread) -class LLMediaTextureUpdateThread : public LLSimpleton, LL::ThreadPool -{ -public: - // follows gSavedSettings "RenderGLMultiThreaded" - static bool sEnabled; - - LLMediaTextureUpdateThread(LLWindow* window); - - // post a function to be executed on the LLMediaTextureUpdateThread background thread - template - bool post(CALLABLE&& func) - { - return getQueue().postIfOpen(std::forward(func)); - } - - void run() override; - -private: - LLWindow* mWindow; - void* mContext = nullptr; - LLAtomicBool mFinished; + LLViewerMediaTexture *updatePlaceholderImage(); }; - #endif // LLVIEWERMEDIA_H diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index ccf4c5bbec..5fed46f437 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1629,6 +1629,7 @@ void LLViewerFetchedTexture::scheduleCreateTexture() mNeedsCreateTexture = TRUE; if (preCreateTexture()) { + ref(); #if LL_IMAGEGL_THREAD_CHECK //grab a copy of the raw image data to make sure it isn't modified pending texture creation U8* data = mRawImage->getData(); @@ -1642,7 +1643,6 @@ void LLViewerFetchedTexture::scheduleCreateTexture() #endif mNeedsCreateTexture = TRUE; auto mainq = LLImageGLThread::sEnabled ? mMainQueue.lock() : nullptr; - ref(); // protect texture from deletion while active on bg queue if (mainq) { mainq->postTo( diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index ba93f4f5f9..b9a5e90df0 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2027,9 +2027,6 @@ LLViewerWindow::LLViewerWindow(const Params& p) gTextureList.init(); LLViewerTextureManager::init() ; gBumpImageList.init(); - - // Init Media texture worker queue - LLViewerMediaImpl::initClass(mWindow, gSavedSettings.getBOOL("RenderGLMultiThreaded")); // Create container for all sub-views LLView::Params rvp; @@ -2419,8 +2416,7 @@ void LLViewerWindow::shutdownGL() LLViewerTextureManager::cleanup() ; SUBSYSTEM_CLEANUP(LLImageGL) ; - SUBSYSTEM_CLEANUP(LLViewerMediaImpl); - + LL_INFOS() << "All textures and llimagegl images are destroyed!" << LL_ENDL ; LL_INFOS() << "Cleaning up select manager" << LL_ENDL; -- cgit v1.2.3 From c38812aa154e01b3a0aac8c7a4a4134e866cfd0a Mon Sep 17 00:00:00 2001 From: Ptolemy Date: Thu, 3 Feb 2022 11:11:46 -0800 Subject: SL-16727: Revert change causing llvieweroctree to not render reflections when shadows are set to projectors cause by commit bb379cb8cc --- indra/llrender/llgl.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 12da961cef..922fcb867b 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -1029,7 +1029,9 @@ void LLGLManager::initExtensions() mHasSync = ExtensionExists("GL_ARB_sync", gGLHExts.mSysExts); mHasMapBufferRange = ExtensionExists("GL_ARB_map_buffer_range", gGLHExts.mSysExts); mHasFlushBufferRange = ExtensionExists("GL_APPLE_flush_buffer_range", gGLHExts.mSysExts); - mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts); + // NOTE: Using extensions breaks reflections when Shadows are set to projector. See: SL-16727 + //mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts); + mHasDepthClamp = FALSE; // mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad #ifdef GL_ARB_framebuffer_object mHasFramebufferObject = ExtensionExists("GL_ARB_framebuffer_object", gGLHExts.mSysExts); -- cgit v1.2.3 From f47730b92c309092d0a5a95e2d49d7ad53230a97 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 14 Feb 2022 18:07:24 +0000 Subject: SL-16418 Media texture update stall fix. Make media texture updates use LLImageGL thread to update, fix AMD sync issue on ImageGL thread and install debug callbacks on LLImageGL thread when debug gl enabled. --- indra/llimage/llimage.cpp | 6 + indra/llimage/llimage.h | 6 + indra/llmath/llvolume.cpp | 2 +- indra/llrender/llgl.cpp | 11 -- indra/llrender/llgltexture.cpp | 12 +- indra/llrender/llgltexture.h | 14 +- indra/llrender/llimagegl.cpp | 139 +++++++++----- indra/llrender/llimagegl.h | 14 +- indra/llrender/llrender.cpp | 20 ++ indra/newview/llviewermedia.cpp | 393 +++++++++++++++++++++++---------------- indra/newview/llviewermedia.h | 13 +- indra/newview/llviewerwindow.cpp | 6 +- 12 files changed, 398 insertions(+), 238 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 15b07e5318..5fa19ce9c6 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -860,6 +860,12 @@ U8* LLImageRaw::reallocateData(S32 size) return res; } +void LLImageRaw::releaseData() +{ + LLImageBase::setSize(0, 0, 0); + LLImageBase::setDataAndSize(nullptr, 0); +} + // virtual void LLImageRaw::deleteData() { diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 354926ee58..7a588cfb03 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -191,6 +191,12 @@ public: /*virtual*/ void deleteData(); /*virtual*/ U8* allocateData(S32 size = -1); /*virtual*/ U8* reallocateData(S32 size); + + // use in conjunction with "no_copy" constructor to release data pointer before deleting + // so that deletion of this LLImageRaw will not free the memory at the "data" parameter + // provided to "no_copy" constructor + void releaseData(); + bool resize(U16 width, U16 height, S8 components); diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index e9ccde5fae..d91a973153 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -88,7 +88,7 @@ const F32 SKEW_MAX = 0.95f; const F32 SCULPT_MIN_AREA = 0.002f; const S32 SCULPT_MIN_AREA_DETAIL = 1; -BOOL gDebugGL = FALSE; +BOOL gDebugGL = FALSE; // See settings.xml "RenderDebugGL" BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm) { diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 922fcb867b..50a5972d28 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -757,17 +757,6 @@ bool LLGLManager::initGL() stop_glerror(); -#if LL_WINDOWS - if (mHasDebugOutput && gDebugGL) - { //setup debug output callback - //glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, GL_TRUE); - glDebugMessageCallbackARB((GLDEBUGPROCARB) gl_debug_callback, NULL); - glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); - } -#endif - - stop_glerror(); - //HACK always disable texture multisample, use FXAA instead mHasTextureMultisample = FALSE; #if LL_WINDOWS diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp index b6a02f1c0a..c7de8bc338 100644 --- a/indra/llrender/llgltexture.cpp +++ b/indra/llrender/llgltexture.cpp @@ -164,11 +164,11 @@ BOOL LLGLTexture::createGLTexture() return mGLTexturep->createGLTexture() ; } -BOOL LLGLTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, BOOL to_create, S32 category) +BOOL LLGLTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, BOOL to_create, S32 category, bool defer_copy) { llassert(mGLTexturep.notNull()) ; - BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category) ; + BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category, defer_copy) ; if(ret) { @@ -260,20 +260,20 @@ LLTexUnit::eTextureType LLGLTexture::getTarget(void) const return mGLTexturep->getTarget() ; } -BOOL LLGLTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height) +BOOL LLGLTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, bool use_new_name /* = false */) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; llassert(mGLTexturep.notNull()) ; - return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height) ; + return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height, 0, use_new_name) ; } -BOOL LLGLTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) +BOOL LLGLTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, bool use_new_name /* = false */) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; llassert(mGLTexturep.notNull()) ; - return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height) ; + return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height, 0, use_new_name) ; } void LLGLTexture::setGLTextureCreated (bool initialized) diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h index 028457c510..216e7f640d 100644 --- a/indra/llrender/llgltexture.h +++ b/indra/llrender/llgltexture.h @@ -124,13 +124,21 @@ public: BOOL hasGLTexture() const ; LLGLuint getTexName() const ; BOOL createGLTexture() ; - BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLGLTexture::OTHER); + + // Create a GL Texture from an image raw + // discard_level - mip level, 0 for highest resultion mip + // imageraw - the image to copy from + // usename - explicit GL name override + // to_create - set to FALSE to force gl texture to not be created + // category - LLGLTexture category for this LLGLTexture + // defer_copy - set to true to allocate GL texture but NOT initialize with imageraw data + BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLGLTexture::OTHER, bool defer_copy = false); void setFilteringOption(LLTexUnit::eTextureFilterOptions option); void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); void setAddressMode(LLTexUnit::eTextureAddressMode mode); - BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height); - BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height); + BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, bool use_new_name = false); + BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, bool use_new_name = false); void setGLTextureCreated (bool initialized); void setCategory(S32 category) ; void setTexName(LLGLuint); // for forcing w/ externally created textures only diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 1e9b9f642e..694c4a7b06 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -550,7 +550,7 @@ bool LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_leve if (width != mWidth || height != mHeight || ncomponents != mComponents) { // Check if dimensions are a power of two! - if (!checkSize(width,height)) + if (!checkSize(width, height)) { LL_WARNS() << llformat("Texture has non power of two dimension: %dx%d",width,height) << LL_ENDL; return false; @@ -674,7 +674,7 @@ void LLImageGL::setImage(const LLImageRaw* imageraw) setImage(rawdata, FALSE); } -BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips, S32 usename) +BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips /* = FALSE */, S32 usename /* = 0 */) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; bool is_compressed = false; @@ -709,8 +709,14 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips, S32 usename) gGL.getTexUnit(0)->bind(this, false, false, usename); - - if (mUseMipMaps) + if (data_in == nullptr) + { + S32 w = getWidth(); + S32 h = getHeight(); + LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h, + mFormatPrimary, mFormatType, (GLvoid*)data_in, mAllowCompression); + } + else if (mUseMipMaps) { if (data_hasmips) { @@ -1069,14 +1075,14 @@ void LLImageGL::postAddToAtlas() stop_glerror(); } -BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update) +BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update /* = FALSE */, bool use_new_name /* = false */) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if (!width || !height) { return TRUE; } - if (mTexName == 0) + if (0 == (use_new_name ? mNewTexName : mTexName)) { // *TODO: Re-enable warning? Ran into thread locking issues? DK 2011-02-18 //LL_WARNS() << "Setting subimage on image without GL texture" << LL_ENDL; @@ -1092,7 +1098,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 // HACK: allow the caller to explicitly force the fast path (i.e. using glTexSubImage2D here instead of calling setImage) even when updating the full texture. if (!force_fast_update && x_pos == 0 && y_pos == 0 && width == getWidth() && height == getHeight() && data_width == width && data_height == height) { - setImage(datap, FALSE); + setImage(datap, FALSE, use_new_name ? mNewTexName : mTexName); } else { @@ -1144,12 +1150,11 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 datap += (y_pos * data_width + x_pos) * getComponents(); // Update the GL texture - BOOL res = gGL.getTexUnit(0)->bindManual(mBindTarget, mTexName); + BOOL res = gGL.getTexUnit(0)->bindManual(mBindTarget, use_new_name ? mNewTexName : mTexName); if (!res) LL_ERRS() << "LLImageGL::setSubImage(): bindTexture failed" << LL_ENDL; stop_glerror(); - glTexSubImage2D(mTarget, 0, x_pos, y_pos, - width, height, mFormatPrimary, mFormatType, datap); + glTexSubImage2D(mTarget, 0, x_pos, y_pos, width, height, mFormatPrimary, mFormatType, datap); gGL.getTexUnit(0)->disable(); stop_glerror(); @@ -1166,10 +1171,10 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 return TRUE; } -BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update) +BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update /* = FALSE */, bool use_new_name /* = false */) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height, force_fast_update); + return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height, force_fast_update, use_new_name); } // Copy sub image from frame buffer @@ -1356,7 +1361,7 @@ BOOL LLImageGL::createGLTexture() return TRUE ; } -BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category) +BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category, bool defer_copy) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; checkActiveThread(); @@ -1386,6 +1391,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S // Actual image width/height = raw image width/height * 2^discard_level S32 raw_w = imageraw->getWidth() ; S32 raw_h = imageraw->getHeight() ; + S32 w = raw_w << discard_level; S32 h = raw_h << discard_level; @@ -1468,15 +1474,24 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S setCategory(category); const U8* rawdata = imageraw->getData(); - return createGLTexture(discard_level, rawdata, FALSE, usename); + return createGLTexture(discard_level, rawdata, FALSE, usename, defer_copy); } -BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) +BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename, bool defer_copy) + // Call with void data, vmem is allocated but unitialized { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; checkActiveThread(); - llassert(data_in); + if (defer_copy) + { + data_in = nullptr; + } + else + { + llassert(data_in); + } + stop_glerror(); if (discard_level < 0) @@ -1486,7 +1501,8 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); - if (mTexName != 0 && discard_level == mCurrentDiscardLevel) + if (!defer_copy // <--- hacky way to force creation of mNewTexName from media texture update + && mTexName != 0 && discard_level == mCurrentDiscardLevel) { // This will only be true if the size has not changed return setImage(data_in, data_hasmips); @@ -1534,36 +1550,12 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } //if we're on the image loading thread, be sure to delete old_texname and update mTexName on the main thread - if (! on_main_thread()) + if (!on_main_thread()) { + if (!defer_copy) { - LL_PROFILE_ZONE_NAMED("cglt - sync"); - if (gGLManager.mHasSync) - { - auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); - glClientWaitSync(sync, 0, 0); - glDeleteSync(sync); - } - else - { - glFinish(); - } + syncToMainThread(); } - - ref(); - LL::WorkQueue::postMaybe( - mMainQueue, - [=]() - { - LL_PROFILE_ZONE_NAMED("cglt - delete callback"); - if (old_texname != 0) - { - LLImageGL::deleteTextures(1, &old_texname); - } - mTexName = mNewTexName; - mNewTexName = 0; - unref(); - }); } else { @@ -1587,6 +1579,55 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ return TRUE; } +void LLImageGL::syncToMainThread() +{ + { + LL_PROFILE_ZONE_NAMED("cglt - sync"); + if (gGLManager.mHasSync) + { + // post a sync to the main thread (will execute before tex name swap lambda below) + auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + glFlush(); + LL::WorkQueue::postMaybe( + mMainQueue, + [=]() + { + LL_PROFILE_ZONE_NAMED("cglt - wait sync"); + { + LL_PROFILE_ZONE_NAMED("glWaitSync"); + glWaitSync(sync, 0, GL_TIMEOUT_IGNORED); + } + { + LL_PROFILE_ZONE_NAMED("glDeleteSync"); + glDeleteSync(sync); + } + }); + } + else + { + glFinish(); + } + } + + ref(); + LL::WorkQueue::postMaybe( + mMainQueue, + [=]() + { + LL_PROFILE_ZONE_NAMED("cglt - delete callback"); + if (mNewTexName != 0) + { + if (mTexName != 0) + { + LLImageGL::deleteTextures(1, &mTexName); + } + mTexName = mNewTexName; + mNewTexName = 0; + unref(); + } + }); +} + BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const { llassert_always(sAllowReadBackRaw) ; @@ -1714,7 +1755,15 @@ void LLImageGL::destroyGLTexture() mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. mTexName = 0; mGLTextureCreated = FALSE ; - } + } + + // clean up any in-flight name change + if (0 != mNewTexName) + { + // Memory is transient, not tracked by sGlobalTextuerMemory + LLImageGL::deleteTextures(1, &mNewTexName); + mNewTexName = 0; + } } //force to invalidate the gl texture, most likely a sculpty texture diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index d6f4b13a51..6c6e327e42 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -110,14 +110,18 @@ public: BOOL createGLTexture() ; BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, - S32 category = sMaxCategories-1); - BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0); + S32 category = sMaxCategories-1, bool defer_copy = false); + BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0, bool defer_copy = false); void setImage(const LLImageRaw* imageraw); BOOL setImage(const U8* data_in, BOOL data_hasmips = FALSE, S32 usename = 0); - BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); - BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); + BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE, bool use_new_name = false); + BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE, bool use_new_name = false); BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height); - + + // wait for gl commands to finish on current thread and push + // a lambda to main thread to swap mNewTexName and mTexName + void syncToMainThread(); + // Read back a raw image for this discard level, if it exists BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const; void destroyGLTexture(); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 92d8e6193f..a03a27cf94 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -36,6 +36,17 @@ #include "lltexture.h" #include "llshadermgr.h" +#if LL_WINDOWS +extern void APIENTRY gl_debug_callback(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + GLvoid* userParam) +; +#endif + thread_local LLRender gGL; // Handy copies of last good GL matrices @@ -860,6 +871,15 @@ LLRender::~LLRender() void LLRender::init() { +#if LL_WINDOWS + if (gGLManager.mHasDebugOutput && gDebugGL) + { //setup debug output callback + //glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, GL_TRUE); + glDebugMessageCallbackARB((GLDEBUGPROCARB) gl_debug_callback, NULL); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); + } +#endif + glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 63f57e81cc..bd60b9f1e2 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -39,6 +39,7 @@ #include "llfilepicker.h" #include "llfloaterwebcontent.h" // for handling window close requests and geometry change requests in media browser windows. #include "llfocusmgr.h" +#include "llimagegl.h" #include "llkeyboard.h" #include "lllogininstance.h" #include "llmarketplacefunctions.h" @@ -635,6 +636,7 @@ static bool proximity_comparitor(const LLViewerMediaImpl* i1, const LLViewerMedi static LLTrace::BlockTimerStatHandle FTM_MEDIA_UPDATE("Update Media"); static LLTrace::BlockTimerStatHandle FTM_MEDIA_SPARE_IDLE("Spare Idle"); static LLTrace::BlockTimerStatHandle FTM_MEDIA_UPDATE_INTEREST("Update/Interest"); +static LLTrace::BlockTimerStatHandle FTM_MEDIA_UPDATE_VOLUME("Update/Volume"); static LLTrace::BlockTimerStatHandle FTM_MEDIA_SORT("Media Sort"); static LLTrace::BlockTimerStatHandle FTM_MEDIA_SORT2("Media Sort 2"); static LLTrace::BlockTimerStatHandle FTM_MEDIA_MISC("Misc"); @@ -654,6 +656,13 @@ void LLViewerMedia::updateMedia(void *dummy_arg) // Enable/disable the plugin read thread LLPluginProcessParent::setUseReadThread(gSavedSettings.getBOOL("PluginUseReadThread")); + // SL-16418 We can't call LLViewerMediaImpl->update() if we are in the state of shutting down. + if(LLApp::isExiting()) + { + setAllMediaEnabled(false); + return; + } + // HACK: we always try to keep a spare running webkit plugin around to improve launch times. // 2017-04-19 Removed CP - this doesn't appear to buy us much and consumes a lot of resources so // removing it for now. @@ -1590,6 +1599,8 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, media_tex->setMediaImpl(); } + mMainQueue = LL::WorkQueue::getInstance("mainloop"); + mTexUpdateQueue = LL::WorkQueue::getInstance("LLImageGL"); // Share work queue with tex loader. } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1676,11 +1687,13 @@ void LLViewerMediaImpl::destroyMediaSource() cancelMimeTypeProbe(); + mLock.lock(); // Delay tear-down while bg thread is updating if(mMediaSource) { mMediaSource->setDeleteOK(true) ; mMediaSource = NULL; // shared pointer } + mLock.unlock(); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -2087,6 +2100,7 @@ void LLViewerMediaImpl::setMute(bool mute) ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::updateVolume() { + LL_RECORD_BLOCK_TIME(FTM_MEDIA_UPDATE_VOLUME); if(mMediaSource) { // always scale the volume by the global media volume @@ -2799,199 +2813,256 @@ static LLTrace::BlockTimerStatHandle FTM_MEDIA_SET_SUBIMAGE("Set Subimage"); void LLViewerMediaImpl::update() { LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; //LL_RECORD_BLOCK_TIME(FTM_MEDIA_DO_UPDATE); - if(mMediaSource == NULL) - { - if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED) - { - // This media source should not be loaded. - } - else if(mPriority <= LLPluginClassMedia::PRIORITY_SLIDESHOW) - { - // Don't load new instances that are at PRIORITY_SLIDESHOW or below. They're just kept around to preserve state. - } + if(mMediaSource == NULL) + { + if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED) + { + // This media source should not be loaded. + } + else if(mPriority <= LLPluginClassMedia::PRIORITY_SLIDESHOW) + { + // Don't load new instances that are at PRIORITY_SLIDESHOW or below. They're just kept around to preserve state. + } else if (!mMimeProbe.expired()) - { - // this media source is doing a MIME type probe -- don't try loading it again. - } - else - { - // This media may need to be loaded. - if(sMediaCreateTimer.hasExpired()) - { - LL_DEBUGS("PluginPriority") << this << ": creating media based on timer expiration" << LL_ENDL; - createMediaSource(); - sMediaCreateTimer.setTimerExpirySec(LLVIEWERMEDIA_CREATE_DELAY); - } - else - { - LL_DEBUGS("PluginPriority") << this << ": NOT creating media (waiting on timer)" << LL_ENDL; - } - } - } - else - { - updateVolume(); + { + // this media source is doing a MIME type probe -- don't try loading it again. + } + else + { + // This media may need to be loaded. + if(sMediaCreateTimer.hasExpired()) + { + LL_DEBUGS("PluginPriority") << this << ": creating media based on timer expiration" << LL_ENDL; + createMediaSource(); + sMediaCreateTimer.setTimerExpirySec(LLVIEWERMEDIA_CREATE_DELAY); + } + else + { + LL_DEBUGS("PluginPriority") << this << ": NOT creating media (waiting on timer)" << LL_ENDL; + } + } + } + else + { + updateVolume(); - // TODO: this is updated every frame - is this bad? - // Removing this as part of the post viewer64 media update - // Removed as not implemented in CEF embedded browser - // See MAINT-8194 for a more fuller description - // updateJavascriptObject(); - } + // TODO: this is updated every frame - is this bad? + // Removing this as part of the post viewer64 media update + // Removed as not implemented in CEF embedded browser + // See MAINT-8194 for a more fuller description + // updateJavascriptObject(); + } - if(mMediaSource == NULL) - { - return; - } + if(mMediaSource == NULL) + { + return; + } - // Make sure a navigate doesn't happen during the idle -- it can cause mMediaSource to get destroyed, which can cause a crash. - setNavigateSuspended(true); + // Make sure a navigate doesn't happen during the idle -- it can cause mMediaSource to get destroyed, which can cause a crash. + setNavigateSuspended(true); - mMediaSource->idle(); + mMediaSource->idle(); - setNavigateSuspended(false); + setNavigateSuspended(false); - if(mMediaSource == NULL) - { - return; - } + if(mMediaSource == NULL) + { + return; + } - if(mMediaSource->isPluginExited()) - { - resetPreviousMediaState(); - destroyMediaSource(); - return; - } + if(mMediaSource->isPluginExited()) + { + resetPreviousMediaState(); + destroyMediaSource(); + return; + } - if(!mMediaSource->textureValid()) - { - return; - } + if(!mMediaSource->textureValid()) + { + return; + } - if(mSuspendUpdates || !mVisible) - { - return; - } + if(mSuspendUpdates || !mVisible) + { + return; + } - LLViewerMediaTexture* placeholder_image = updatePlaceholderImage(); + + LLViewerMediaTexture* media_tex; + U8* data; + S32 data_width; + S32 data_height; + S32 x_pos; + S32 y_pos; + S32 width; + S32 height; + + if (preMediaTexUpdate(media_tex, data, data_width, data_height, x_pos, y_pos, width, height)) + { + // Push update to worker thread + auto main_queue = LLImageGLThread::sEnabled ? mMainQueue.lock() : nullptr; + if (main_queue) + { + mTextureUpdatePending = true; + ref(); // protect texture from deletion while active on bg queue + media_tex->ref(); + main_queue->postTo( + mTexUpdateQueue, // Worker thread queue + [=]() // work done on update worker thread + { + doMediaTexUpdate(media_tex, data, data_width, data_height, x_pos, y_pos, width, height, true); + }, + [=]() // callback to main thread + { + mTextureUpdatePending = false; + media_tex->unref(); + unref(); + }); + } + else + { + doMediaTexUpdate(media_tex, data, data_width, data_height, x_pos, y_pos, width, height, false); // otherwise, update on main thread + } + } +} - if(placeholder_image) - { - LLRect dirty_rect; +bool LLViewerMediaImpl::preMediaTexUpdate(LLViewerMediaTexture*& media_tex, U8*& data, S32& data_width, S32& data_height, S32& x_pos, S32& y_pos, S32& width, S32& height) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; - // Since we're updating this texture, we know it's playing. Tell the texture to do its replacement magic so it gets rendered. - placeholder_image->setPlaying(TRUE); + bool retval = false; - if(mMediaSource->getDirty(&dirty_rect)) - { - // Constrain the dirty rect to be inside the texture - S32 x_pos = llmax(dirty_rect.mLeft, 0); - S32 y_pos = llmax(dirty_rect.mBottom, 0); - S32 width = llmin(dirty_rect.mRight, placeholder_image->getWidth()) - x_pos; - S32 height = llmin(dirty_rect.mTop, placeholder_image->getHeight()) - y_pos; + if (!mTextureUpdatePending) + { + media_tex = updateMediaImage(); - if(width > 0 && height > 0) - { + if (media_tex && mMediaSource) + { + LLRect dirty_rect; + S32 media_width = mMediaSource->getTextureWidth(); + S32 media_height = mMediaSource->getTextureHeight(); + //S32 media_depth = mMediaSource->getTextureDepth(); - U8* data = NULL; - { - LL_PROFILE_ZONE_NAMED_CATEGORY_MEDIA("media get data"); //LL_RECORD_BLOCK_TIME(FTM_MEDIA_GET_DATA); - data = mMediaSource->getBitsData(); - } + // Since we're updating this texture, we know it's playing. Tell the texture to do its replacement magic so it gets rendered. + media_tex->setPlaying(TRUE); - if(data != NULL) - { - // Offset the pixels pointer to match x_pos and y_pos - data += ( x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth() ); - data += ( y_pos * mMediaSource->getTextureDepth() ); + if (mMediaSource->getDirty(&dirty_rect)) + { + // Constrain the dirty rect to be inside the texture + x_pos = llmax(dirty_rect.mLeft, 0); + y_pos = llmax(dirty_rect.mBottom, 0); + width = llmin(dirty_rect.mRight, media_width) - x_pos; + height = llmin(dirty_rect.mTop, media_height) - y_pos; - { - LL_PROFILE_ZONE_NAMED_CATEGORY_MEDIA("media set subimage"); //LL_RECORD_BLOCK_TIME(FTM_MEDIA_SET_SUBIMAGE); - placeholder_image->setSubImage( - data, - mMediaSource->getBitsWidth(), - mMediaSource->getBitsHeight(), - x_pos, - y_pos, - width, - height); - } - } + if (width > 0 && height > 0) + { + data = mMediaSource->getBitsData(); + data_width = mMediaSource->getWidth(); + data_height = mMediaSource->getHeight(); + + if (data != NULL) + { + // data is ready to be copied to GL + retval = true; + } + } - } + mMediaSource->resetDirty(); + } + } + } - mMediaSource->resetDirty(); - } - } + return retval; } +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::doMediaTexUpdate(LLViewerMediaTexture* media_tex, U8* data, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, bool sync) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; + mLock.lock(); // don't allow media source tear-down during update + + // wrap "data" in an LLImageRaw but do NOT make a copy + LLPointer raw = new LLImageRaw(data, media_tex->getWidth(), media_tex->getHeight(), media_tex->getComponents(), true); + + // Allocate GL texture based on LLImageRaw but do NOT copy to GL + media_tex->createGLTexture(0, raw, 0, TRUE, LLGLTexture::OTHER, true); + + // copy just the subimage covered by the image raw to GL + media_tex->setSubImage(data, data_width, data_height, x_pos, y_pos, width, height, sync); + media_tex->getGLTexture()->syncToMainThread(); + + // release the data pointer before freeing raw so LLImageRaw destructor doesn't + // free memory at data pointer + raw->releaseData(); + + mLock.unlock(); +} ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::updateImagesMediaStreams() { } - ////////////////////////////////////////////////////////////////////////////////////////// -LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage() +LLViewerMediaTexture* LLViewerMediaImpl::updateMediaImage() { - if(mTextureId.isNull()) - { - // The code that created this instance will read from the plugin's bits. - return NULL; - } - - LLViewerMediaTexture* placeholder_image = LLViewerTextureManager::getMediaTexture( mTextureId ); - - if (mNeedsNewTexture - || placeholder_image->getUseMipMaps() - || (placeholder_image->getWidth() != mMediaSource->getTextureWidth()) - || (placeholder_image->getHeight() != mMediaSource->getTextureHeight()) - || (mTextureUsedWidth != mMediaSource->getWidth()) - || (mTextureUsedHeight != mMediaSource->getHeight()) - ) - { - LL_DEBUGS("Media") << "initializing media placeholder" << LL_ENDL; - LL_DEBUGS("Media") << "movie image id " << mTextureId << LL_ENDL; - - int texture_width = mMediaSource->getTextureWidth(); - int texture_height = mMediaSource->getTextureHeight(); - int texture_depth = mMediaSource->getTextureDepth(); - - // MEDIAOPT: check to see if size actually changed before doing work - placeholder_image->destroyGLTexture(); - // MEDIAOPT: apparently just calling setUseMipMaps(FALSE) doesn't work? - placeholder_image->reinit(FALSE); // probably not needed - - // MEDIAOPT: seems insane that we actually have to make an imageraw then - // immediately discard it - LLPointer raw = new LLImageRaw(texture_width, texture_height, texture_depth); - // Clear the texture to the background color, ignoring alpha. - // convert background color channels from [0.0, 1.0] to [0, 255]; - raw->clear(int(mBackgroundColor.mV[VX] * 255.0f), int(mBackgroundColor.mV[VY] * 255.0f), int(mBackgroundColor.mV[VZ] * 255.0f), 0xff); - int discard_level = 0; - - // ask media source for correct GL image format constants - placeholder_image->setExplicitFormat(mMediaSource->getTextureFormatInternal(), - mMediaSource->getTextureFormatPrimary(), - mMediaSource->getTextureFormatType(), - mMediaSource->getTextureFormatSwapBytes()); - - placeholder_image->createGLTexture(discard_level, raw); - - // MEDIAOPT: set this dynamically on play/stop - // FIXME -// placeholder_image->mIsMediaTexture = true; - mNeedsNewTexture = false; - - // If the amount of the texture being drawn by the media goes down in either width or height, - // recreate the texture to avoid leaving parts of the old image behind. - mTextureUsedWidth = mMediaSource->getWidth(); - mTextureUsedHeight = mMediaSource->getHeight(); - } + LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; + if (!mMediaSource) + { + return nullptr; // not ready for updating + } - return placeholder_image; + llassert(!mTextureId.isNull()); + LLViewerMediaTexture* media_tex = LLViewerTextureManager::getMediaTexture( mTextureId ); + + if ( mNeedsNewTexture + || media_tex->getUseMipMaps() + || (media_tex->getWidth() != mMediaSource->getTextureWidth()) + || (media_tex->getHeight() != mMediaSource->getTextureHeight()) + || (mTextureUsedWidth != mMediaSource->getWidth()) + || (mTextureUsedHeight != mMediaSource->getHeight()) + ) + { + LL_DEBUGS("Media") << "initializing media placeholder" << LL_ENDL; + LL_DEBUGS("Media") << "movie image id " << mTextureId << LL_ENDL; + + int texture_width = mMediaSource->getTextureWidth(); + int texture_height = mMediaSource->getTextureHeight(); + int texture_depth = mMediaSource->getTextureDepth(); + + // MEDIAOPT: check to see if size actually changed before doing work + media_tex->destroyGLTexture(); + // MEDIAOPT: apparently just calling setUseMipMaps(FALSE) doesn't work? + media_tex->reinit(FALSE); // probably not needed + + // MEDIAOPT: seems insane that we actually have to make an imageraw then + // immediately discard it + LLPointer raw = new LLImageRaw(texture_width, texture_height, texture_depth); + // Clear the texture to the background color, ignoring alpha. + // convert background color channels from [0.0, 1.0] to [0, 255]; + raw->clear(int(mBackgroundColor.mV[VX] * 255.0f), int(mBackgroundColor.mV[VY] * 255.0f), int(mBackgroundColor.mV[VZ] * 255.0f), 0xff); + + // ask media source for correct GL image format constants + media_tex->setExplicitFormat(mMediaSource->getTextureFormatInternal(), + mMediaSource->getTextureFormatPrimary(), + mMediaSource->getTextureFormatType(), + mMediaSource->getTextureFormatSwapBytes()); + + int discard_level = 0; + media_tex->createGLTexture(discard_level, raw); + + // MEDIAOPT: set this dynamically on play/stop + // FIXME +// media_tex->mIsMediaTexture = true; + mNeedsNewTexture = false; + + // If the amount of the texture being drawn by the media goes down in either width or height, + // recreate the texture to avoid leaving parts of the old image behind. + mTextureUsedWidth = mMediaSource->getWidth(); + mTextureUsedHeight = mMediaSource->getHeight(); + } + return media_tex; } diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 71cec5125d..806692929a 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -197,7 +197,7 @@ public: U8 media_loop); ~LLViewerMediaImpl(); - + // Override inherited version from LLViewerMediaEventEmitter virtual void emitEvent(LLPluginClassMedia* self, LLViewerMediaObserver::EMediaEvent event); @@ -266,6 +266,8 @@ public: void scaleTextureCoords(const LLVector2& texture_coords, S32 *x, S32 *y); void update(); + bool preMediaTexUpdate(LLViewerMediaTexture*& media_tex, U8*& data, S32& data_width, S32& data_height, S32& x_pos, S32& y_pos, S32& width, S32& height); + void doMediaTexUpdate(LLViewerMediaTexture* media_tex, U8* data, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, bool sync); void updateImagesMediaStreams(); LLUUID getMediaTextureID() const; @@ -427,6 +429,7 @@ private: private: // a single media url with some data and an impl. boost::shared_ptr mMediaSource; + LLMutex mLock; F64 mZoomFactor; LLUUID mTextureId; bool mMovieImageHasMips; @@ -446,6 +449,7 @@ private: S32 mTextureUsedWidth; S32 mTextureUsedHeight; bool mSuspendUpdates; + bool mTextureUpdatePending = false; bool mVisible; ECursorType mLastSetCursor; EMediaNavState mMediaNavState; @@ -479,7 +483,7 @@ private: LLNotificationPtr mNotification; bool mCleanBrowser; // force the creation of a clean browsing target with full options enabled static std::vector sMimeTypesFailed; - + LLPointer mRawImage; //backing buffer for texture updates private: BOOL mIsUpdated ; std::list< LLVOVolume* > mObjectList ; @@ -489,7 +493,10 @@ private: bool mCanceling; private: - LLViewerMediaTexture *updatePlaceholderImage(); + LLViewerMediaTexture *updateMediaImage(); + LL::WorkQueue::weak_t mMainQueue; + LL::WorkQueue::weak_t mTexUpdateQueue; + }; #endif // LLVIEWERMEDIA_H diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index b9a5e90df0..80850265bc 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2023,12 +2023,12 @@ LLViewerWindow::LLViewerWindow(const Params& p) // Init the image list. Must happen after GL is initialized and before the images that // LLViewerWindow needs are requested. - LLImageGL::initClass(mWindow, LLViewerTexture::MAX_GL_IMAGE_CATEGORY, false, gSavedSettings.getBOOL("RenderGLMultiThreaded")); + LLImageGL::initClass(mWindow, LLViewerTexture::MAX_GL_IMAGE_CATEGORY, false, gSavedSettings.getBOOL("RenderGLMultiThreaded")); gTextureList.init(); LLViewerTextureManager::init() ; gBumpImageList.init(); - // Create container for all sub-views + // Create container for all sub-views LLView::Params rvp; rvp.name("root"); rvp.rect(mWindowRectScaled); @@ -2416,7 +2416,7 @@ void LLViewerWindow::shutdownGL() LLViewerTextureManager::cleanup() ; SUBSYSTEM_CLEANUP(LLImageGL) ; - + LL_INFOS() << "All textures and llimagegl images are destroyed!" << LL_ENDL ; LL_INFOS() << "Cleaning up select manager" << LL_ENDL; -- cgit v1.2.3 From 892f7d98d5da2c329472a7075a88e010277b86b0 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 17 Feb 2022 20:55:32 +0200 Subject: SL-16861 Animesh and avatar color change fix --- indra/newview/llvovolume.cpp | 7 +++++-- indra/newview/llvovolume.h | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index a60bece037..49be0765a6 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -225,6 +225,7 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mNumFaces = 0; mLODChanged = FALSE; mSculptChanged = FALSE; + mColorChanged = FALSE; mSpotLightPriority = 0.f; mMediaImplList.resize(getNumTEs()); @@ -2031,7 +2032,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) was_regen_faces = lodOrSculptChanged(drawable, compiled); drawable->setState(LLDrawable::REBUILD_VOLUME); } - else if (mSculptChanged || mLODChanged) + else if (mSculptChanged || mLODChanged || mColorChanged) { compiled = TRUE; was_regen_faces = lodOrSculptChanged(drawable, compiled); @@ -2043,7 +2044,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) genBBoxes(FALSE); } - else if (mLODChanged || mSculptChanged) + else if (mLODChanged || mSculptChanged || mColorChanged) { dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); compiled = TRUE; @@ -2075,6 +2076,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) mLODChanged = FALSE; mSculptChanged = FALSE; mFaceMappingChanged = FALSE; + mColorChanged = FALSE; return LLViewerObject::updateGeometry(drawable); } @@ -2213,6 +2215,7 @@ S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color) if (mDrawable.notNull() && retval) { // These should only happen on updates which are not the initial update. + mColorChanged = TRUE; mDrawable->setState(LLDrawable::REBUILD_COLOR); dirtyMesh(); } diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index d158044f5d..4cb7a5481c 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -413,6 +413,7 @@ private: S32 mLOD; BOOL mLODChanged; BOOL mSculptChanged; + BOOL mColorChanged; F32 mSpotLightPriority; LLMatrix4 mRelativeXform; LLMatrix3 mRelativeXformInvTrans; -- cgit v1.2.3 From 0d6aa3c0fe184ae00899304cb3f71315f5c73314 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 17 Feb 2022 22:52:23 +0000 Subject: SL-16815 Remove frame stalls from occlusion queries, bumpmap updates, and querying for available video memory. --- indra/llrender/llgl.cpp | 90 +---------------- indra/llrender/llgl.h | 45 --------- indra/llrender/llgltexture.cpp | 14 +-- indra/llrender/llgltexture.h | 7 +- indra/llrender/llimagegl.cpp | 119 ++++++++++++++++------ indra/llrender/llimagegl.h | 17 ++-- indra/llwindow/llwindowwin32.cpp | 1 + indra/newview/lldrawpoolbump.cpp | 203 ++++++++++++++++++++++++-------------- indra/newview/lldrawpoolbump.h | 2 + indra/newview/llviewerdisplay.cpp | 3 - indra/newview/llviewermedia.cpp | 7 +- indra/newview/llvieweroctree.cpp | 93 +++++++++++------ indra/newview/llviewertexture.cpp | 24 ++--- indra/newview/pipeline.cpp | 5 - 14 files changed, 316 insertions(+), 314 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 50a5972d28..639d1fba32 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -2150,95 +2150,6 @@ LLGLUserClipPlane::~LLGLUserClipPlane() disable(); } -LLGLNamePool::LLGLNamePool() -{ -} - -LLGLNamePool::~LLGLNamePool() -{ -} - -void LLGLNamePool::upkeep() -{ - std::sort(mNameList.begin(), mNameList.end(), CompareUsed()); -} - -void LLGLNamePool::cleanup() -{ - for (name_list_t::iterator iter = mNameList.begin(); iter != mNameList.end(); ++iter) - { - releaseName(iter->name); - } - - mNameList.clear(); -} - -GLuint LLGLNamePool::allocate() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; -#if LL_GL_NAME_POOLING - for (name_list_t::iterator iter = mNameList.begin(); iter != mNameList.end(); ++iter) - { - if (!iter->used) - { - iter->used = TRUE; - return iter->name; - } - } - - NameEntry entry; - entry.name = allocateName(); - entry.used = TRUE; - mNameList.push_back(entry); - - return entry.name; -#else - return allocateName(); -#endif -} - -void LLGLNamePool::release(GLuint name) -{ -#if LL_GL_NAME_POOLING - for (name_list_t::iterator iter = mNameList.begin(); iter != mNameList.end(); ++iter) - { - if (iter->name == name) - { - if (iter->used) - { - iter->used = FALSE; - return; - } - else - { - LL_ERRS() << "Attempted to release a pooled name that is not in use!" << LL_ENDL; - } - } - } - LL_ERRS() << "Attempted to release a non pooled name!" << LL_ENDL; -#else - releaseName(name); -#endif -} - -//static -void LLGLNamePool::upkeepPools() -{ - for (auto& pool : instance_snapshot()) - { - pool.upkeep(); - } -} - -//static -void LLGLNamePool::cleanupPools() -{ - for (auto& pool : instance_snapshot()) - { - pool.cleanup(); - } -} - LLGLDepthTest::LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled, GLenum depth_func) : mPrevDepthEnabled(sDepthEnabled), mPrevDepthFunc(sDepthFunc), mPrevWriteEnabled(sWriteEnabled) { @@ -2460,3 +2371,4 @@ extern "C" } #endif + diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index ec97eb0faa..52338364e6 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -366,51 +366,6 @@ public: ~LLGLSquashToFarClip(); }; -/* - Generic pooling scheme for things which use GL names (used for occlusion queries and vertex buffer objects). - Prevents thrashing of GL name caches by avoiding calls to glGenFoo and glDeleteFoo. -*/ -class LLGLNamePool : public LLInstanceTracker -{ -public: - typedef LLInstanceTracker tracker_t; - - struct NameEntry - { - GLuint name; - BOOL used; - }; - - struct CompareUsed - { - bool operator()(const NameEntry& lhs, const NameEntry& rhs) - { - return lhs.used < rhs.used; //FALSE entries first - } - }; - - typedef std::vector name_list_t; - name_list_t mNameList; - - LLGLNamePool(); - virtual ~LLGLNamePool(); - - void upkeep(); - void cleanup(); - - GLuint allocate(); - void release(GLuint name); - - static void upkeepPools(); - static void cleanupPools(); - -protected: - typedef std::vector pool_list_t; - - virtual GLuint allocateName() = 0; - virtual void releaseName(GLuint name) = 0; -}; - /* Interface for objects that need periodic GL updates applied to them. Used to synchronize GL updates with GL thread. diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp index c7de8bc338..e012eb9a62 100644 --- a/indra/llrender/llgltexture.cpp +++ b/indra/llrender/llgltexture.cpp @@ -164,11 +164,11 @@ BOOL LLGLTexture::createGLTexture() return mGLTexturep->createGLTexture() ; } -BOOL LLGLTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, BOOL to_create, S32 category, bool defer_copy) +BOOL LLGLTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, BOOL to_create, S32 category, bool defer_copy, LLGLuint* tex_name) { - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()); - BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category, defer_copy) ; + BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category, defer_copy, tex_name) ; if(ret) { @@ -260,20 +260,20 @@ LLTexUnit::eTextureType LLGLTexture::getTarget(void) const return mGLTexturep->getTarget() ; } -BOOL LLGLTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, bool use_new_name /* = false */) +BOOL LLGLTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; llassert(mGLTexturep.notNull()) ; - return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height, 0, use_new_name) ; + return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height, 0, use_name) ; } -BOOL LLGLTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, bool use_new_name /* = false */) +BOOL LLGLTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; llassert(mGLTexturep.notNull()) ; - return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height, 0, use_new_name) ; + return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height, 0, use_name) ; } void LLGLTexture::setGLTextureCreated (bool initialized) diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h index 216e7f640d..8cfe7b62de 100644 --- a/indra/llrender/llgltexture.h +++ b/indra/llrender/llgltexture.h @@ -132,13 +132,14 @@ public: // to_create - set to FALSE to force gl texture to not be created // category - LLGLTexture category for this LLGLTexture // defer_copy - set to true to allocate GL texture but NOT initialize with imageraw data - BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLGLTexture::OTHER, bool defer_copy = false); + // tex_name - if not null, will be set to the GL name of the texture created + BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLGLTexture::OTHER, bool defer_copy = false, LLGLuint* tex_name = nullptr); void setFilteringOption(LLTexUnit::eTextureFilterOptions option); void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); void setAddressMode(LLTexUnit::eTextureAddressMode mode); - BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, bool use_new_name = false); - BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, bool use_new_name = false); + BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name = 0); + BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name = 0); void setGLTextureCreated (bool initialized); void setCategory(S32 category) ; void setTexName(LLGLuint); // for forcing w/ externally created textures only diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 694c4a7b06..110074bdc0 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -40,6 +40,7 @@ #include "llglslshader.h" #include "llrender.h" #include "llwindow.h" +#include "llframetimer.h" #if !LL_IMAGEGL_THREAD_CHECK #define checkActiveThread() @@ -1075,14 +1076,15 @@ void LLImageGL::postAddToAtlas() stop_glerror(); } -BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update /* = FALSE */, bool use_new_name /* = false */) +BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update /* = FALSE */, LLGLuint use_name) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if (!width || !height) { return TRUE; } - if (0 == (use_new_name ? mNewTexName : mTexName)) + LLGLuint tex_name = use_name != 0 ? use_name : mTexName; + if (0 == tex_name) { // *TODO: Re-enable warning? Ran into thread locking issues? DK 2011-02-18 //LL_WARNS() << "Setting subimage on image without GL texture" << LL_ENDL; @@ -1098,7 +1100,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 // HACK: allow the caller to explicitly force the fast path (i.e. using glTexSubImage2D here instead of calling setImage) even when updating the full texture. if (!force_fast_update && x_pos == 0 && y_pos == 0 && width == getWidth() && height == getHeight() && data_width == width && data_height == height) { - setImage(datap, FALSE, use_new_name ? mNewTexName : mTexName); + setImage(datap, FALSE, tex_name); } else { @@ -1150,7 +1152,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 datap += (y_pos * data_width + x_pos) * getComponents(); // Update the GL texture - BOOL res = gGL.getTexUnit(0)->bindManual(mBindTarget, use_new_name ? mNewTexName : mTexName); + BOOL res = gGL.getTexUnit(0)->bindManual(mBindTarget, tex_name); if (!res) LL_ERRS() << "LLImageGL::setSubImage(): bindTexture failed" << LL_ENDL; stop_glerror(); @@ -1171,10 +1173,10 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 return TRUE; } -BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update /* = FALSE */, bool use_new_name /* = false */) +BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update /* = FALSE */, LLGLuint use_name) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height, force_fast_update, use_new_name); + return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height, force_fast_update, use_name); } // Copy sub image from frame buffer @@ -1361,7 +1363,7 @@ BOOL LLImageGL::createGLTexture() return TRUE ; } -BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category, bool defer_copy) +BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category, bool defer_copy, LLGLuint* tex_name) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; checkActiveThread(); @@ -1474,15 +1476,17 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S setCategory(category); const U8* rawdata = imageraw->getData(); - return createGLTexture(discard_level, rawdata, FALSE, usename, defer_copy); + return createGLTexture(discard_level, rawdata, FALSE, usename, defer_copy, tex_name); } -BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename, bool defer_copy) +BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename, bool defer_copy, LLGLuint* tex_name) // Call with void data, vmem is allocated but unitialized { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; checkActiveThread(); + bool main_thread = on_main_thread(); + if (defer_copy) { data_in = nullptr; @@ -1501,29 +1505,40 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); - if (!defer_copy // <--- hacky way to force creation of mNewTexName from media texture update + if (main_thread // <--- always force creation of mNewTexName when not on main thread && mTexName != 0 && discard_level == mCurrentDiscardLevel) { + LL_PROFILE_ZONE_NAMED("cglt - early setImage"); // This will only be true if the size has not changed + if (tex_name != nullptr) + { + *tex_name = mTexName; + } return setImage(data_in, data_hasmips); } GLuint old_texname = mTexName; - + GLuint new_texname = 0; if (usename != 0) { - mNewTexName = usename; + llassert(main_thread); + new_texname = usename; } else { - LLImageGL::generateTextures(1, &mNewTexName); + LLImageGL::generateTextures(1, &new_texname); { - gGL.getTexUnit(0)->bind(this, false, false, mNewTexName); + gGL.getTexUnit(0)->bind(this, false, false, new_texname); glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel - discard_level); } } + if (tex_name != nullptr) + { + *tex_name = new_texname; + } + if (mUseMipMaps) { mAutoGenMips = gGLManager.mHasMipMapGeneration; @@ -1531,9 +1546,12 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ mCurrentDiscardLevel = discard_level; - if (!setImage(data_in, data_hasmips, mNewTexName)) { - return FALSE; + LL_PROFILE_ZONE_NAMED("cglt - late setImage"); + if (!setImage(data_in, data_hasmips, new_texname)) + { + return FALSE; + } } // Set texture options to our defaults. @@ -1550,11 +1568,11 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } //if we're on the image loading thread, be sure to delete old_texname and update mTexName on the main thread - if (!on_main_thread()) + if (!main_thread) { if (!defer_copy) { - syncToMainThread(); + syncToMainThread(new_texname); } } else @@ -1564,8 +1582,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ { LLImageGL::deleteTextures(1, &old_texname); } - mTexName = mNewTexName; - mNewTexName = 0; + mTexName = new_texname; } mTextureMemory = (S32Bytes)getMipBytes(mCurrentDiscardLevel); @@ -1579,13 +1596,36 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ return TRUE; } -void LLImageGL::syncToMainThread() +void update_free_vram() +{ + LL_PROFILE_ZONE_SCOPED; + + if (gGLManager.mHasATIMemInfo) + { + S32 meminfo[4]; + glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo); + LLImageGLThread::sFreeVRAMMegabytes = meminfo[0]; + + } + else if (gGLManager.mHasNVXMemInfo) + { + S32 free_memory; + glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory); + LLImageGLThread::sFreeVRAMMegabytes = free_memory / 1024; + } +} + +void LLImageGL::syncToMainThread(LLGLuint new_tex_name) { + LL_PROFILE_ZONE_SCOPED; { LL_PROFILE_ZONE_NAMED("cglt - sync"); if (gGLManager.mHasSync) { // post a sync to the main thread (will execute before tex name swap lambda below) + // glFlush calls here are partly superstitious and partly backed by observation + // on AMD hardware + glFlush(); auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); glFlush(); LL::WorkQueue::postMaybe( @@ -1615,17 +1655,27 @@ void LLImageGL::syncToMainThread() [=]() { LL_PROFILE_ZONE_NAMED("cglt - delete callback"); - if (mNewTexName != 0) + if (new_tex_name != 0) { if (mTexName != 0) { LLImageGL::deleteTextures(1, &mTexName); } - mTexName = mNewTexName; - mNewTexName = 0; + mTexName = new_tex_name; unref(); } }); + + + //update free vram periodically + static LLFrameTimer timer; + + if (timer.getElapsedTimeF32() > 1.f) //call this once per second. + { + update_free_vram(); + timer.reset(); + } + } BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const @@ -1756,14 +1806,6 @@ void LLImageGL::destroyGLTexture() mTexName = 0; mGLTextureCreated = FALSE ; } - - // clean up any in-flight name change - if (0 != mNewTexName) - { - // Memory is transient, not tracked by sGlobalTextuerMemory - LLImageGL::deleteTextures(1, &mNewTexName); - mNewTexName = 0; - } } //force to invalidate the gl texture, most likely a sculpty texture @@ -2306,6 +2348,8 @@ void LLImageGL::checkActiveThread() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, nummips); */ +std::atomic LLImageGLThread::sFreeVRAMMegabytes; + LLImageGLThread::LLImageGLThread(LLWindow* window) // We want exactly one thread, but a very large capacity: we never want // anyone, especially inner-loop render code, to have to block on post() @@ -2332,3 +2376,14 @@ void LLImageGLThread::run() gGL.shutdown(); mWindow->destroySharedContext(mContext); } + +S32 LLImageGLThread::getFreeVRAMMegabytes() +{ + if (!sEnabled) + { + update_free_vram(); + } + + return sFreeVRAMMegabytes; +} + diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 6c6e327e42..50706890f9 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -110,17 +110,17 @@ public: BOOL createGLTexture() ; BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, - S32 category = sMaxCategories-1, bool defer_copy = false); - BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0, bool defer_copy = false); + S32 category = sMaxCategories-1, bool defer_copy = false, LLGLuint* tex_name = nullptr); + BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0, bool defer_copy = false, LLGLuint* tex_name = nullptr); void setImage(const LLImageRaw* imageraw); BOOL setImage(const U8* data_in, BOOL data_hasmips = FALSE, S32 usename = 0); - BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE, bool use_new_name = false); - BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE, bool use_new_name = false); + BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE, LLGLuint use_name = 0); + BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE, LLGLuint use_name = 0); BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height); // wait for gl commands to finish on current thread and push // a lambda to main thread to swap mNewTexName and mTexName - void syncToMainThread(); + void syncToMainThread(LLGLuint new_tex_name); // Read back a raw image for this discard level, if it exists BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const; @@ -224,7 +224,7 @@ private: bool mGLTextureCreated ; LLGLuint mTexName; - LLGLuint mNewTexName = 0; // tex name set by background thread to be applied in main thread + //LLGLuint mNewTexName = 0; // tex name set by background thread to be applied in main thread U16 mWidth; U16 mHeight; S8 mCurrentDiscardLevel; @@ -324,6 +324,9 @@ public: // follows gSavedSettings "RenderGLMultiThreaded" static bool sEnabled; + // free video memory in megabytes + static std::atomic sFreeVRAMMegabytes; + LLImageGLThread(LLWindow* window); // post a function to be executed on the LLImageGL background thread @@ -335,6 +338,8 @@ public: void run() override; + static S32 getFreeVRAMMegabytes(); + private: LLWindow* mWindow; void* mContext = nullptr; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 8c792daac0..5ce51bb43e 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -3564,6 +3564,7 @@ void LLWindowWin32::swapBuffers() { LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32; ASSERT_MAIN_THREAD(); + glFlush(); //superstitious flush for maybe frame stall removal? SwapBuffers(mhDC); LL_PROFILER_GPU_COLLECT diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 471b0e2c48..20287a7777 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -54,6 +54,8 @@ // static LLStandardBumpmap gStandardBumpmapList[TEM_BUMPMAP_COUNT]; +LL::WorkQueue::weak_t LLBumpImageList::sMainQueue; +LL::WorkQueue::weak_t LLBumpImageList::sTexUpdateQueue; // static U32 LLStandardBumpmap::sStandardBumpmapCount = 0; @@ -761,6 +763,8 @@ void LLBumpImageList::init() LLStandardBumpmap::init(); LLStandardBumpmap::restoreGL(); + sMainQueue = LL::WorkQueue::getInstance("mainloop"); + sTexUpdateQueue = LL::WorkQueue::getInstance("LLImageGL"); // Share work queue with tex loader. } void LLBumpImageList::clear() @@ -909,10 +913,7 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText } else { - LLPointer raw = new LLImageRaw(1,1,1); - raw->clear(0x77, 0x77, 0xFF, 0xFF); - - (*entries_list)[src_image->getID()] = LLViewerTextureManager::getLocalTexture( raw.get(), TRUE); + (*entries_list)[src_image->getID()] = LLViewerTextureManager::getLocalTexture( TRUE ); bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image } @@ -1043,10 +1044,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI iter->second->getWidth() != src->getWidth() || iter->second->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution { //make sure an entry exists for this image - LLPointer raw = new LLImageRaw(1,1,1); - raw->clear(0x77, 0x77, 0xFF, 0xFF); - - entries_list[src_vi->getID()] = LLViewerTextureManager::getLocalTexture( raw.get(), TRUE); + entries_list[src_vi->getID()] = LLViewerTextureManager::getLocalTexture(TRUE); iter = entries_list.find(src_vi->getID()); } } @@ -1166,108 +1164,161 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI } //--------------------------------------------------- - // immediately assign bump to a global smart pointer in case some local smart pointer + // immediately assign bump to a smart pointer in case some local smart pointer // accidentally releases it. - LLPointer bump = LLViewerTextureManager::getLocalTexture( TRUE ); + LLPointer bump = iter->second; if (!LLPipeline::sRenderDeferred) { bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA); - bump->createGLTexture(0, dst_image); + + auto tex_queue = LLImageGLThread::sEnabled ? sTexUpdateQueue.lock() : nullptr; + + if (tex_queue) + { //dispatch creation to background thread + LLImageRaw* dst_ptr = dst_image; + LLViewerTexture* bump_ptr = bump; + dst_ptr->ref(); + bump_ptr->ref(); + tex_queue->post( + [=]() + { + LL_PROFILE_ZONE_NAMED("bil - create texture"); + bump_ptr->createGLTexture(0, dst_ptr); + bump_ptr->unref(); + dst_ptr->unref(); + }); + } + else + { + bump->createGLTexture(0, dst_image); + } } else { //convert to normal map //disable compression on normal maps to prevent errors below bump->getGLTexture()->setAllowCompression(false); + bump->getGLTexture()->setUseMipMaps(TRUE); - { - bump->setExplicitFormat(GL_RGBA8, GL_ALPHA); - bump->createGLTexture(0, dst_image); - } + auto* bump_ptr = bump.get(); + auto* dst_ptr = dst_image.get(); - { - gPipeline.mScreen.bindTarget(); - - LLGLDepthTest depth(GL_FALSE); - LLGLDisable cull(GL_CULL_FACE); - LLGLDisable blend(GL_BLEND); - gGL.setColorMask(TRUE, TRUE); - gNormalMapGenProgram.bind(); + bump_ptr->ref(); + dst_ptr->ref(); - static LLStaticHashedString sNormScale("norm_scale"); - static LLStaticHashedString sStepX("stepX"); - static LLStaticHashedString sStepY("stepY"); + bump_ptr->setExplicitFormat(GL_RGBA8, GL_ALPHA); - gNormalMapGenProgram.uniform1f(sNormScale, gSavedSettings.getF32("RenderNormalMapScale")); - gNormalMapGenProgram.uniform1f(sStepX, 1.f/bump->getWidth()); - gNormalMapGenProgram.uniform1f(sStepY, 1.f/bump->getHeight()); + auto create_texture = [bump_ptr, dst_ptr]() + { + LL_PROFILE_ZONE_NAMED("bil - create texture deferred"); + bump_ptr->createGLTexture(0, dst_ptr); + }; - LLVector2 v((F32) bump->getWidth()/gPipeline.mScreen.getWidth(), - (F32) bump->getHeight()/gPipeline.mScreen.getHeight()); + auto gen_normal_map = [bump_ptr, dst_ptr]() + { + LL_PROFILE_ZONE_NAMED("bil - generate normal map"); + gPipeline.mScreen.bindTarget(); - gGL.getTexUnit(0)->bind(bump); - - S32 width = bump->getWidth(); - S32 height = bump->getHeight(); + LLGLDepthTest depth(GL_FALSE); + LLGLDisable cull(GL_CULL_FACE); + LLGLDisable blend(GL_BLEND); + gGL.setColorMask(TRUE, TRUE); + gNormalMapGenProgram.bind(); - S32 screen_width = gPipeline.mScreen.getWidth(); - S32 screen_height = gPipeline.mScreen.getHeight(); + static LLStaticHashedString sNormScale("norm_scale"); + static LLStaticHashedString sStepX("stepX"); + static LLStaticHashedString sStepY("stepY"); - glViewport(0, 0, screen_width, screen_height); + gNormalMapGenProgram.uniform1f(sNormScale, gSavedSettings.getF32("RenderNormalMapScale")); + gNormalMapGenProgram.uniform1f(sStepX, 1.f / bump_ptr->getWidth()); + gNormalMapGenProgram.uniform1f(sStepY, 1.f / bump_ptr->getHeight()); - for (S32 left = 0; left < width; left += screen_width) - { - S32 right = left + screen_width; - right = llmin(right, width); - - F32 left_tc = (F32) left/ width; - F32 right_tc = (F32) right/width; + LLVector2 v((F32)bump_ptr->getWidth() / gPipeline.mScreen.getWidth(), + (F32)bump_ptr->getHeight() / gPipeline.mScreen.getHeight()); - for (S32 bottom = 0; bottom < height; bottom += screen_height) - { - S32 top = bottom+screen_height; - top = llmin(top, height); + gGL.getTexUnit(0)->bind(bump_ptr); - F32 bottom_tc = (F32) bottom/height; - F32 top_tc = (F32)(bottom+screen_height)/height; - top_tc = llmin(top_tc, 1.f); + S32 width = bump_ptr->getWidth(); + S32 height = bump_ptr->getHeight(); - F32 screen_right = (F32) (right-left)/screen_width; - F32 screen_top = (F32) (top-bottom)/screen_height; + S32 screen_width = gPipeline.mScreen.getWidth(); + S32 screen_height = gPipeline.mScreen.getHeight(); - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.texCoord2f(left_tc, bottom_tc); - gGL.vertex2f(0, 0); + glViewport(0, 0, screen_width, screen_height); - gGL.texCoord2f(left_tc, top_tc); - gGL.vertex2f(0, screen_top); + for (S32 left = 0; left < width; left += screen_width) + { + S32 right = left + screen_width; + right = llmin(right, width); - gGL.texCoord2f(right_tc, bottom_tc); - gGL.vertex2f(screen_right, 0); + F32 left_tc = (F32)left / width; + F32 right_tc = (F32)right / width; - gGL.texCoord2f(right_tc, top_tc); - gGL.vertex2f(screen_right, screen_top); + for (S32 bottom = 0; bottom < height; bottom += screen_height) + { + S32 top = bottom + screen_height; + top = llmin(top, height); - gGL.end(); + F32 bottom_tc = (F32)bottom / height; + F32 top_tc = (F32)(bottom + screen_height) / height; + top_tc = llmin(top_tc, 1.f); - gGL.flush(); + F32 screen_right = (F32)(right - left) / screen_width; + F32 screen_top = (F32)(top - bottom) / screen_height; - S32 w = right-left; - S32 h = top-bottom; + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.texCoord2f(left_tc, bottom_tc); + gGL.vertex2f(0, 0); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, left, bottom, 0, 0, w, h); - } - } + gGL.texCoord2f(left_tc, top_tc); + gGL.vertex2f(0, screen_top); - glGenerateMipmap(GL_TEXTURE_2D); + gGL.texCoord2f(right_tc, bottom_tc); + gGL.vertex2f(screen_right, 0); - gPipeline.mScreen.flush(); + gGL.texCoord2f(right_tc, top_tc); + gGL.vertex2f(screen_right, screen_top); - gNormalMapGenProgram.unbind(); - - //generateNormalMapFromAlpha(dst_image, nrm_image); - } + gGL.end(); + + gGL.flush(); + + S32 w = right - left; + S32 h = top - bottom; + + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, left, bottom, 0, 0, w, h); + } + } + + glGenerateMipmap(GL_TEXTURE_2D); + + gPipeline.mScreen.flush(); + + gNormalMapGenProgram.unbind(); + + //generateNormalMapFromAlpha(dst_image, nrm_image); + + bump_ptr->unref(); + dst_ptr->unref(); + }; + + auto main_queue = LLImageGLThread::sEnabled ? sMainQueue.lock() : nullptr; + + if (main_queue) + { //dispatch creation to background thread + LLImageRaw* dst_ptr = dst_image; + LLViewerTexture* bump_ptr = bump; + dst_ptr->ref(); + bump_ptr->ref(); + + main_queue->postTo(sTexUpdateQueue, create_texture, gen_normal_map); + } + else + { + create_texture(); + gen_normal_map(); + } } iter->second = bump; // derefs (and deletes) old image diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h index 38744a7d98..6e21859738 100644 --- a/indra/newview/lldrawpoolbump.h +++ b/indra/newview/lldrawpoolbump.h @@ -161,6 +161,8 @@ private: typedef std::unordered_map > bump_image_map_t; bump_image_map_t mBrightnessEntries; bump_image_map_t mDarknessEntries; + static LL::WorkQueue::weak_t sMainQueue; + static LL::WorkQueue::weak_t sTexUpdateQueue; }; extern LLBumpImageList gBumpImageList; diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index b5d3dc5d30..4fc1bdbec3 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -649,9 +649,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES); } - //upkeep gl name pools - LLGLNamePool::upkeepPools(); - stop_glerror(); display_update_camera(); stop_glerror(); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index bd60b9f1e2..42bd5d8367 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -2986,11 +2986,12 @@ void LLViewerMediaImpl::doMediaTexUpdate(LLViewerMediaTexture* media_tex, U8* da LLPointer raw = new LLImageRaw(data, media_tex->getWidth(), media_tex->getHeight(), media_tex->getComponents(), true); // Allocate GL texture based on LLImageRaw but do NOT copy to GL - media_tex->createGLTexture(0, raw, 0, TRUE, LLGLTexture::OTHER, true); + LLGLuint tex_name = 0; + media_tex->createGLTexture(0, raw, 0, TRUE, LLGLTexture::OTHER, true, &tex_name); // copy just the subimage covered by the image raw to GL - media_tex->setSubImage(data, data_width, data_height, x_pos, y_pos, width, height, sync); - media_tex->getGLTexture()->syncToMainThread(); + media_tex->setSubImage(data, data_width, data_height, x_pos, y_pos, width, height, tex_name); + media_tex->getGLTexture()->syncToMainThread(tex_name); // release the data pointer before freeing raw so LLImageRaw destructor doesn't // free memory at data pointer diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp index 3cdef0ebff..65e9fa533d 100644 --- a/indra/newview/llvieweroctree.cpp +++ b/indra/newview/llvieweroctree.cpp @@ -787,42 +787,73 @@ void LLViewerOctreeGroup::checkStates() //occulsion culling functions and classes //------------------------------------------------------------------------------------------- std::set LLOcclusionCullingGroup::sPendingQueries; -class LLOcclusionQueryPool : public LLGLNamePool + +static std::queue sFreeQueries; + +U32 LLOcclusionCullingGroup::getNewOcclusionQueryObjectName() { -public: - LLOcclusionQueryPool() - { - } + LL_PROFILE_ZONE_SCOPED; + // TODO: refactor this to a general purpose name pool + static GLuint occlusion_queries[2][1024]; + static std::atomic query_count[2]; + static S32 query_page = -1; + + //reuse any query names that have been freed + if (!sFreeQueries.empty()) + { + GLuint ret = sFreeQueries.front(); + sFreeQueries.pop(); + return ret; + } -protected: + // first call, immediately fill entire name pool + if (query_page == -1) + { + glGenQueriesARB(1024, occlusion_queries[0]); + glGenQueriesARB(1024, occlusion_queries[1]); + query_page = 0; + query_count[0] = 1024; + query_count[1] = 1024; + } - virtual GLuint allocateName() - { - GLuint ret = 0; + if (query_count[query_page] == 0) //this page is empty + { + //check the other page + query_page = (query_page + 1) % 2; - glGenQueriesARB(1, &ret); - - return ret; - } + if (query_count[query_page] == 0) + { + //the other page is also empty, generate immediately and return + GLuint ret; + glGenQueriesARB(1, &ret); + return ret; + } + } - virtual void releaseName(GLuint name) - { -#if LL_TRACK_PENDING_OCCLUSION_QUERIES - LLOcclusionCullingGroup::sPendingQueries.erase(name); -#endif - glDeleteQueriesARB(1, &name); - } -}; + GLuint ret = occlusion_queries[query_page][--query_count[query_page]]; -static LLOcclusionQueryPool sQueryPool; -U32 LLOcclusionCullingGroup::getNewOcclusionQueryObjectName() -{ - return sQueryPool.allocate(); + if (query_count[query_page] == 0) + { //exhausted this page, replenish on background thread + S32 page = query_page; + LL::WorkQueue::postMaybe(LL::WorkQueue::getInstance("LLImageGL"), + [=]() + { + LL_PROFILE_ZONE_NAMED("glGenQueries bg"); + if (query_count[page] == 0) // <-- protect against redundant attempts to replenish + { + glGenQueriesARB(1024, occlusion_queries[page]); + query_count[page] = 1024; + glFlush(); + } + }); + } + + return ret; } void LLOcclusionCullingGroup::releaseOcclusionQueryObjectName(GLuint name) { - sQueryPool.release(name); + sFreeQueries.push(name); } //===================================== @@ -1243,7 +1274,10 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh //store which frame this query was issued on mOcclusionIssued[LLViewerCamera::sCurCameraID] = gFrameCount; - glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]); + { + LL_PROFILE_ZONE_NAMED("glBeginQuery"); + glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]); + } LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; llassert(shader); @@ -1282,7 +1316,10 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh } } - glEndQueryARB(mode); + { + LL_PROFILE_ZONE_NAMED("glEndQuery"); + glEndQueryARB(mode); + } } } diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 5fed46f437..fa2c070ea0 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -515,9 +515,10 @@ void LLViewerTexture::getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &p { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; static LLFrameTimer timer; + static S32Megabytes gpu_res = S32Megabytes(S32_MAX); static S32Megabytes physical_res = S32Megabytes(S32_MAX); - + if (timer.getElapsedTimeF32() < GPU_MEMORY_CHECK_WAIT_TIME) //call this once per second. { gpu = gpu_res; @@ -527,22 +528,11 @@ void LLViewerTexture::getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &p timer.reset(); { - if (gGLManager.mHasATIMemInfo) - { - S32 meminfo[4]; - glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo); - gpu_res = (S32Megabytes)meminfo[0]; - - //check main memory, only works for windows. - LLMemory::updateMemoryInfo(); - physical_res = LLMemory::getAvailableMemKB(); - } - else if (gGLManager.mHasNVXMemInfo) - { - S32 free_memory; - glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory); - gpu_res = (S32Megabytes)(free_memory / 1024); - } + gpu_res = (S32Megabytes) LLImageGLThread::getFreeVRAMMegabytes(); + + //check main memory, only works for windows. + LLMemory::updateMemoryInfo(); + physical_res = LLMemory::getAvailableMemKB(); gpu = gpu_res; physical = physical_res; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 8d45e64bf8..ac242c2bf7 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -7267,11 +7267,6 @@ void LLPipeline::doResetVertexBuffers(bool forced) SUBSYSTEM_CLEANUP(LLVertexBuffer); - //delete all name pool caches - LLGLNamePool::cleanupPools(); - - - if (LLVertexBuffer::sGLCount > 0) { LL_WARNS() << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << LL_ENDL; -- cgit v1.2.3 From a8b5ef66a97e0a34c55a738a6fd275cafd4cd273 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 18 Feb 2022 13:14:16 -0600 Subject: SL-16886 Fix for bad batching parameters for some rigged meshes. --- indra/newview/llvovolume.cpp | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 49be0765a6..e583f7176d 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5910,23 +5910,25 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) U32 geometryBytes = 0; + // generate render batches for static geometry U32 extra_mask = LLVertexBuffer::MAP_TEXTURE_INDEX; - geometryBytes += genDrawInfo(group, simple_mask | extra_mask, sSimpleFaces[0], simple_count[0], FALSE, batch_textures); - geometryBytes += genDrawInfo(group, fullbright_mask | extra_mask, sFullbrightFaces[0], fullbright_count[0], FALSE, batch_textures); - geometryBytes += genDrawInfo(group, alpha_mask | extra_mask, sAlphaFaces[0], alpha_count[0], TRUE, batch_textures); - geometryBytes += genDrawInfo(group, bump_mask | extra_mask, sBumpFaces[0], bump_count[0], FALSE, FALSE); - geometryBytes += genDrawInfo(group, norm_mask | extra_mask, sNormFaces[0], norm_count[0], FALSE, FALSE); - geometryBytes += genDrawInfo(group, spec_mask | extra_mask, sSpecFaces[0], spec_count[0], FALSE, FALSE); - geometryBytes += genDrawInfo(group, normspec_mask | extra_mask, sNormSpecFaces[0], normspec_count[0], FALSE, FALSE); - - extra_mask |= LLVertexBuffer::MAP_WEIGHT4; - geometryBytes += genDrawInfo(group, simple_mask | extra_mask, sSimpleFaces[1], simple_count[1], FALSE, batch_textures, TRUE); - geometryBytes += genDrawInfo(group, fullbright_mask | extra_mask, sFullbrightFaces[1], fullbright_count[1], FALSE, batch_textures, TRUE); - geometryBytes += genDrawInfo(group, alpha_mask | extra_mask, sAlphaFaces[1], alpha_count[1], TRUE, batch_textures, TRUE); - geometryBytes += genDrawInfo(group, bump_mask | extra_mask, sBumpFaces[1], bump_count[1], FALSE, TRUE); - geometryBytes += genDrawInfo(group, norm_mask | extra_mask, sNormFaces[1], norm_count[1], FALSE, TRUE); - geometryBytes += genDrawInfo(group, spec_mask | extra_mask, sSpecFaces[1], spec_count[1], FALSE, TRUE); - geometryBytes += genDrawInfo(group, normspec_mask | extra_mask, sNormSpecFaces[1], normspec_count[1], FALSE, TRUE); + BOOL alpha_sort = TRUE; + BOOL rigged = FALSE; + for (int i = 0; i < 2; ++i) //two sets, static and rigged) + { + geometryBytes += genDrawInfo(group, simple_mask | extra_mask, sSimpleFaces[i], simple_count[i], FALSE, batch_textures, rigged); + geometryBytes += genDrawInfo(group, fullbright_mask | extra_mask, sFullbrightFaces[i], fullbright_count[i], FALSE, batch_textures, rigged); + geometryBytes += genDrawInfo(group, alpha_mask | extra_mask, sAlphaFaces[i], alpha_count[i], alpha_sort, batch_textures, rigged); + geometryBytes += genDrawInfo(group, bump_mask | extra_mask, sBumpFaces[i], bump_count[i], FALSE, FALSE, rigged); + geometryBytes += genDrawInfo(group, norm_mask | extra_mask, sNormFaces[i], norm_count[i], FALSE, FALSE, rigged); + geometryBytes += genDrawInfo(group, spec_mask | extra_mask, sSpecFaces[i], spec_count[i], FALSE, FALSE, rigged); + geometryBytes += genDrawInfo(group, normspec_mask | extra_mask, sNormSpecFaces[i], normspec_count[i], FALSE, FALSE, rigged); + + // for rigged set, add weights and disable alpha sorting (rigged items use depth buffer) + extra_mask |= LLVertexBuffer::MAP_WEIGHT4; + alpha_sort = FALSE; + rigged = TRUE; + } group->mGeometryBytes = geometryBytes; -- cgit v1.2.3 From 74ac4ae0ebc52ad76366bb688ba9c9635b26d6c2 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 18 Feb 2022 19:41:54 +0200 Subject: SL-16811 Shape preview images do not display all of the attachments. --- indra/newview/lltoolmorph.cpp | 13 +--- indra/newview/pipeline.cpp | 161 ++++++++++++++++++++++++++++++++++++++++++ indra/newview/pipeline.h | 1 + 3 files changed, 164 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp index b2e8348ffd..b5eb2880ae 100644 --- a/indra/newview/lltoolmorph.cpp +++ b/indra/newview/lltoolmorph.cpp @@ -239,17 +239,8 @@ BOOL LLVisualParamHint::render() LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE); - if (gAgentAvatarp->mDrawable.notNull() && - gAgentAvatarp->mDrawable->getFace(0)) - { - LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)gAgentAvatarp->mDrawable->getFace(0)->getPool(); - LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); - gGL.flush(); - gGL.setSceneBlendType(LLRender::BT_REPLACE); - avatarPoolp->renderAvatars(gAgentAvatarp); // renders only one avatar - gGL.setSceneBlendType(LLRender::BT_ALPHA); - gGL.flush(); - } + gPipeline.previewAvatar(gAgentAvatarp); + gAgentAvatarp->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight); mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight); LLViewerWearable* wearable = (LLViewerWearable*)mWearablePtr; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index ac242c2bf7..5fe883b714 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -11133,6 +11133,167 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) LLGLState::checkTextureChannels(); } +static LLTrace::BlockTimerStatHandle FTM_PREVIEW_AVATAR("Preview Avatar"); + +void LLPipeline::previewAvatar(LLVOAvatar* avatar) +{ + LL_RECORD_BLOCK_TIME(FTM_PREVIEW_AVATAR); + + LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); + gGL.flush(); + gGL.setSceneBlendType(LLRender::BT_REPLACE); + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + + static LLCullResult result; + result.clear(); + grabReferences(result); + + if (!avatar || !avatar->mDrawable) + { + LL_WARNS_ONCE("AvatarRenderPipeline") << "Avatar is " << (avatar ? "not drawable" : "null") << LL_ENDL; + return; + } + LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID() << " is drawable" << LL_ENDL; + + assertInitialized(); + + pushRenderTypeMask(); + + { + //hide world geometry + clearRenderTypeMask( + RENDER_TYPE_SKY, + RENDER_TYPE_WL_SKY, + RENDER_TYPE_GROUND, + RENDER_TYPE_TERRAIN, + RENDER_TYPE_GRASS, + RENDER_TYPE_CONTROL_AV, // Animesh + RENDER_TYPE_TREE, + RENDER_TYPE_VOIDWATER, + RENDER_TYPE_WATER, + RENDER_TYPE_PASS_GRASS, + RENDER_TYPE_HUD, + RENDER_TYPE_PARTICLES, + RENDER_TYPE_CLOUDS, + RENDER_TYPE_HUD_PARTICLES, + END_RENDER_TYPES + ); + } + + S32 occlusion = sUseOcclusion; + sUseOcclusion = 0; + + sReflectionRender = !sRenderDeferred; + + sShadowRender = true; + sImpostorRender = true; // Likely not needed for previews + + LLViewerCamera* viewer_camera = LLViewerCamera::getInstance(); + + { + markVisible(avatar->mDrawable, *viewer_camera); + + LLVOAvatar::attachment_map_t::iterator iter; + for (iter = avatar->mAttachmentPoints.begin(); + iter != avatar->mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment *attachment = iter->second; + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + if (LLViewerObject* attached_object = attachment_iter->get()) + { + markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera); + } + } + } + } + + stateSort(*LLViewerCamera::getInstance(), result); + + LLCamera camera = *viewer_camera; + + F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha; + + if (LLPipeline::sRenderDeferred) + { + renderGeomDeferred(camera); + + renderGeomPostDeferred(camera); + } + else + { + renderGeom(camera); + } + + LLDrawPoolAvatar::sMinimumAlpha = old_alpha; + + { //create alpha mask based on depth buffer + if (LLPipeline::sRenderDeferred) + { + GLuint buff = GL_COLOR_ATTACHMENT0; + LL_PROFILER_GPU_ZONEC("gl.DrawBuffersARB", 0x8000FF); + glDrawBuffersARB(1, &buff); + } + + LLGLDisable blend(GL_BLEND); + + gGL.setColorMask(false, true); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); + + gGL.flush(); + + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + + static const F32 clip_plane = 0.99999f; + + gDebugProgram.bind(); + + gGL.begin(LLRender::QUADS); + gGL.vertex3f(-1, -1, clip_plane); + gGL.vertex3f(1, -1, clip_plane); + gGL.vertex3f(1, 1, clip_plane); + gGL.vertex3f(-1, 1, clip_plane); + gGL.end(); + gGL.flush(); + + gDebugProgram.unbind(); + + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + } + + sUseOcclusion = occlusion; + sReflectionRender = false; + sImpostorRender = false; + sShadowRender = false; + popRenderTypeMask(); + + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + + LLVertexBuffer::unbind(); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + + gGL.setSceneBlendType(LLRender::BT_ALPHA); + gGL.flush(); +} + bool LLPipeline::hasRenderBatches(const U32 type) const { return sCull->getRenderMapSize(type) > 0; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 6114aa4f6c..df5c060417 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -135,6 +135,7 @@ public: void resetVertexBuffers(LLDrawable* drawable); void generateImpostor(LLVOAvatar* avatar); + void previewAvatar(LLVOAvatar* avatar); void bindScreenToTexture(); void renderFinalize(); -- cgit v1.2.3 From 7c90b82ff772df4f8e200ef83c2ecf577b6bdec0 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 18 Feb 2022 15:37:55 -0600 Subject: SL-16815 Better occlusion query name pool. Leverage pool FILO nature to avoid reusing a query while the GPU is still chewing on it. --- indra/newview/llvieweroctree.cpp | 70 ++++++++++++---------------------------- 1 file changed, 20 insertions(+), 50 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp index 65e9fa533d..5eda75753e 100644 --- a/indra/newview/llvieweroctree.cpp +++ b/indra/newview/llvieweroctree.cpp @@ -790,70 +790,36 @@ std::set LLOcclusionCullingGroup::sPendingQueries; static std::queue sFreeQueries; +#define QUERY_POOL_SIZE 1024 + U32 LLOcclusionCullingGroup::getNewOcclusionQueryObjectName() { LL_PROFILE_ZONE_SCOPED; - // TODO: refactor this to a general purpose name pool - static GLuint occlusion_queries[2][1024]; - static std::atomic query_count[2]; - static S32 query_page = -1; - //reuse any query names that have been freed - if (!sFreeQueries.empty()) + if (sFreeQueries.empty()) { - GLuint ret = sFreeQueries.front(); - sFreeQueries.pop(); - return ret; - } - - // first call, immediately fill entire name pool - if (query_page == -1) - { - glGenQueriesARB(1024, occlusion_queries[0]); - glGenQueriesARB(1024, occlusion_queries[1]); - query_page = 0; - query_count[0] = 1024; - query_count[1] = 1024; - } - - if (query_count[query_page] == 0) //this page is empty - { - //check the other page - query_page = (query_page + 1) % 2; - - if (query_count[query_page] == 0) + //seed 1024 query names into the free query pool + GLuint queries[1024]; + glGenQueriesARB(1024, queries); + for (int i = 0; i < 1024; ++i) { - //the other page is also empty, generate immediately and return - GLuint ret; - glGenQueriesARB(1, &ret); - return ret; + sFreeQueries.push(queries[i]); } } - GLuint ret = occlusion_queries[query_page][--query_count[query_page]]; - - if (query_count[query_page] == 0) - { //exhausted this page, replenish on background thread - S32 page = query_page; - LL::WorkQueue::postMaybe(LL::WorkQueue::getInstance("LLImageGL"), - [=]() - { - LL_PROFILE_ZONE_NAMED("glGenQueries bg"); - if (query_count[page] == 0) // <-- protect against redundant attempts to replenish - { - glGenQueriesARB(1024, occlusion_queries[page]); - query_count[page] = 1024; - glFlush(); - } - }); - } - + // pull from pool + GLuint ret = sFreeQueries.front(); + sFreeQueries.pop(); return ret; } void LLOcclusionCullingGroup::releaseOcclusionQueryObjectName(GLuint name) { - sFreeQueries.push(name); + if (name != 0) + { + LL_PROFILE_ZONE_SCOPED; + sFreeQueries.push(name); + } } //===================================== @@ -1276,6 +1242,10 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh { LL_PROFILE_ZONE_NAMED("glBeginQuery"); + + //get an occlusion query that hasn't been used in awhile + releaseOcclusionQueryObjectName(mOcclusionQuery[LLViewerCamera::sCurCameraID]); + mOcclusionQuery[LLViewerCamera::sCurCameraID] = getNewOcclusionQueryObjectName(); glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]); } -- cgit v1.2.3 From 1461e4d437996784cc8afe5d4b3bfa873d3dbfa1 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 18 Feb 2022 15:52:24 -0600 Subject: SL-16815 Fix for crash when disabling ALM. --- indra/newview/lldrawpoolbump.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra') diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 20287a7777..7d03cb7609 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -1218,6 +1218,10 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI auto gen_normal_map = [bump_ptr, dst_ptr]() { LL_PROFILE_ZONE_NAMED("bil - generate normal map"); + if (gNormalMapGenProgram.mProgramObject == 0) + { + return; + } gPipeline.mScreen.bindTarget(); LLGLDepthTest depth(GL_FALSE); -- cgit v1.2.3 From 9f10853c03293f845d9a17adcf8de7ea23a0a778 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Mon, 21 Feb 2022 16:07:58 +0200 Subject: SL-16887 FIXED Crash in LLNetMap::draw --- indra/newview/llnetmap.cpp | 4 ++++ indra/newview/lltracker.cpp | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index 937f36b6fc..1240ce7c0f 100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -147,6 +147,10 @@ void LLNetMap::setScale( F32 scale ) void LLNetMap::draw() { + if (!LLWorld::instanceExists()) + { + return; + } LL_PROFILE_ZONE_SCOPED; static LLFrameTimer map_timer; static LLUIColor map_avatar_color = LLUIColorTable::instance().getColor("MapAvatarColor", LLColor4::white); diff --git a/indra/newview/lltracker.cpp b/indra/newview/lltracker.cpp index 728d0c9417..320554c39e 100644 --- a/indra/newview/lltracker.cpp +++ b/indra/newview/lltracker.cpp @@ -109,7 +109,12 @@ void LLTracker::stopTracking(bool clear_ui) // static virtual void LLTracker::drawHUDArrow() { - if (!gSavedSettings.getBOOL("RenderTrackerBeacon")) return; + if (!LLWorld::instanceExists()) + { + return; + } + + if (!gSavedSettings.getBOOL("RenderTrackerBeacon")) return; if (gViewerWindow->getProgressView()->getVisible()) return; -- cgit v1.2.3 From 97f6736d7fe2575023eff3a6429855c19d9f92f5 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Mon, 21 Feb 2022 17:46:27 +0200 Subject: Cached setting should be used in draw() calls --- indra/newview/lltracker.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/lltracker.cpp b/indra/newview/lltracker.cpp index 320554c39e..ab4ad5817b 100644 --- a/indra/newview/lltracker.cpp +++ b/indra/newview/lltracker.cpp @@ -113,8 +113,12 @@ void LLTracker::drawHUDArrow() { return; } - - if (!gSavedSettings.getBOOL("RenderTrackerBeacon")) return; + + static LLCachedControl render_beacon(gSavedSettings, "RenderTrackerBeacon", true); + if (!render_beacon) + { + return; + } if (gViewerWindow->getProgressView()->getVisible()) return; -- cgit v1.2.3 From e24acd81e0cf47c1a8f39e2485daf81c39d26ca3 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 21 Feb 2022 21:31:19 +0200 Subject: SL-16892 Fix crash at getCameraOffsetInitial getCameraOffsetInitial() call can happen before init() --- indra/newview/llagentcamera.cpp | 19 ++++++++++--------- indra/newview/llagentcamera.h | 6 ------ 2 files changed, 10 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index ed6c3c307f..84a41113be 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -210,9 +210,6 @@ void LLAgentCamera::init() mCameraPreset = (ECameraPreset) gSavedSettings.getU32("CameraPresetType"); - mCameraOffsetInitial = gSavedSettings.getControl("CameraOffsetRearView"); - mFocusOffsetInitial = gSavedSettings.getControl("FocusOffsetRearView"); - mCameraCollidePlane.clearVec(); mCurrentCameraDistance = getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale"); mTargetCameraDistance = mCurrentCameraDistance; @@ -1672,8 +1669,8 @@ LLVector3d LLAgentCamera::calcThirdPersonFocusOffset() agent_rot *= ((LLViewerObject*)(gAgentAvatarp->getParent()))->getRenderRotation(); } - focus_offset = convert_from_llsd(mFocusOffsetInitial->get(), TYPE_VEC3D, ""); - return focus_offset * agent_rot; + static LLCachedControl focus_offset_initial(gSavedSettings, "FocusOffsetRearView", LLVector3d()); + return focus_offset_initial * agent_rot; } void LLAgentCamera::setupSitCamera() @@ -1810,8 +1807,9 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) } else { - local_camera_offset = mCameraZoomFraction * getCameraOffsetInitial() * gSavedSettings.getF32("CameraOffsetScale"); - + static LLCachedControl camera_offset_scale(gSavedSettings, "CameraOffsetScale"); + local_camera_offset = mCameraZoomFraction * getCameraOffsetInitial() * camera_offset_scale; + // are we sitting down? if (isAgentAvatarValid() && gAgentAvatarp->getParent()) { @@ -2028,12 +2026,15 @@ bool LLAgentCamera::isJoystickCameraUsed() LLVector3 LLAgentCamera::getCameraOffsetInitial() { - return convert_from_llsd(mCameraOffsetInitial->get(), TYPE_VEC3, ""); + // getCameraOffsetInitial and getFocusOffsetInitial can be called on update from idle before init() + static LLCachedControl camera_offset_initial (gSavedSettings, "CameraOffsetRearView", LLVector3()); + return camera_offset_initial; } LLVector3d LLAgentCamera::getFocusOffsetInitial() { - return convert_from_llsd(mFocusOffsetInitial->get(), TYPE_VEC3D, ""); + static LLCachedControl focus_offset_initial(gSavedSettings, "FocusOffsetRearView", LLVector3d()); + return focus_offset_initial; } F32 LLAgentCamera::getCameraMaxZoomDistance() diff --git a/indra/newview/llagentcamera.h b/indra/newview/llagentcamera.h index ec1ed433d7..89680f95dc 100644 --- a/indra/newview/llagentcamera.h +++ b/indra/newview/llagentcamera.h @@ -131,12 +131,6 @@ private: /** Camera preset in Third Person Mode */ ECameraPreset mCameraPreset; - /** Initial camera offset */ - LLPointer mCameraOffsetInitial; - - /** Initial focus offset */ - LLPointer mFocusOffsetInitial; - LLQuaternion mInitSitRot; //-------------------------------------------------------------------- -- cgit v1.2.3 From 4e31ff1d7e05ff376fc1c66156eb76cccbdd5f38 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 21 Feb 2022 23:11:17 +0200 Subject: SL-16056 Load cloud texture only once --- indra/newview/llvoavatar.cpp | 5 +++-- indra/newview/llvoavatar.h | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 2d34e28b93..31035f666d 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -619,6 +619,7 @@ F32 LLVOAvatar::sUnbakedTime = 0.f; F32 LLVOAvatar::sUnbakedUpdateTime = 0.f; F32 LLVOAvatar::sGreyTime = 0.f; F32 LLVOAvatar::sGreyUpdateTime = 0.f; +LLPointer LLVOAvatar::sCloudTexture = NULL; //----------------------------------------------------------------------------- // Helper functions @@ -1136,6 +1137,7 @@ void LLVOAvatar::initClass() LLControlAvatar::sRegionChangedSlot = gAgent.addRegionChangedCallback(&LLControlAvatar::onRegionChanged); + sCloudTexture = LLViewerTextureManager::getFetchedTextureFromFile("cloud-particle.j2c"); } @@ -3080,8 +3082,7 @@ void LLVOAvatar::idleUpdateLoadingEffect() particle_parameters.mPartData.mStartColor = LLColor4(1, 1, 1, 0.5f); particle_parameters.mPartData.mEndColor = LLColor4(1, 1, 1, 0.0f); particle_parameters.mPartData.mStartScale.mV[VX] = 0.8f; - LLViewerTexture* cloud = LLViewerTextureManager::getFetchedTextureFromFile("cloud-particle.j2c"); - particle_parameters.mPartImageID = cloud->getID(); + particle_parameters.mPartImageID = sCloudTexture->getID(); particle_parameters.mMaxAge = 0.f; particle_parameters.mPattern = LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE; particle_parameters.mInnerAngle = F_PI; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 7c2d71802e..ba67007fa9 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -336,7 +336,8 @@ public: static F32 sLODFactor; // user-settable LOD factor static F32 sPhysicsLODFactor; // user-settable physics LOD factor static BOOL sJointDebug; // output total number of joints being touched for each avatar - static BOOL sDebugAvatarRotation; + + static LLPointer sCloudTexture; //-------------------------------------------------------------------- // Region state -- cgit v1.2.3 From 900c13d361671c35cd5899dc99bbfbc9c5ec2200 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 22 Feb 2022 00:05:38 +0200 Subject: SL-16892 Fix incorrect width of dropdown menus --- indra/llui/llcombobox.cpp | 29 +++++++++++++++++++++++++++++ indra/llui/llcombobox.h | 3 +++ 2 files changed, 32 insertions(+) (limited to 'indra') diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index bcc653a602..9ca05a16f3 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -113,6 +113,10 @@ LLComboBox::LLComboBox(const LLComboBox::Params& p) } mArrowImage = button_params.image_unselected; + if (mArrowImage.notNull()) + { + mImageLoadedConnection = mArrowImage->addLoadedCallback(boost::bind(&LLComboBox::imageLoaded, this)); + } mButton = LLUICtrlFactory::create(button_params); @@ -183,6 +187,7 @@ LLComboBox::~LLComboBox() // explicitly disconect this signal, since base class destructor might fire top lost mTopLostSignalConnection.disconnect(); + mImageLoadedConnection.disconnect(); } @@ -1074,6 +1079,30 @@ void LLComboBox::onSetHighlight() const } } +void LLComboBox::imageLoaded() +{ + static LLUICachedControl drop_shadow_button("DropShadowButton", 0); + + if (mAllowTextEntry) + { + LLRect rect = getLocalRect(); + S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; + S32 shadow_size = drop_shadow_button; + mButton->setRect(LLRect(getRect().getWidth() - llmax(8, arrow_width) - 2 * shadow_size, + rect.mTop, rect.mRight, rect.mBottom)); + if (mButton->getVisible()) + { + // recalculate field size + if (mTextEntry) + { + LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); + text_entry_rect.mRight -= llmax(8, arrow_width) + 2 * drop_shadow_button; + mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE); + } + } + } +} + //============================================================================ // LLCtrlListInterface functions diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h index e17d6cdfb4..cac8850a25 100644 --- a/indra/llui/llcombobox.h +++ b/indra/llui/llcombobox.h @@ -105,6 +105,8 @@ protected: virtual std::string _getSearchText() const; virtual void onSetHighlight() const; + void imageLoaded(); + public: // LLView interface virtual void onFocusLost(); @@ -244,6 +246,7 @@ private: commit_callback_t mTextChangedCallback; commit_callback_t mSelectionCallback; boost::signals2::connection mTopLostSignalConnection; + boost::signals2::connection mImageLoadedConnection; commit_signal_t mOnReturnSignal; S32 mLastSelectedIndex; }; -- cgit v1.2.3 From 1c5c45f27317d6ee7c2c30de11f43aeee3855434 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 22 Feb 2022 14:58:50 -0600 Subject: SL-16815 Fix for broken media texture updates when multithreaded GL is disabled. --- indra/llrender/llimagegl.cpp | 86 ++++++++++++++++++++++----------------- indra/llrender/llimagegl.h | 3 ++ indra/newview/lldrawpoolbump.cpp | 5 --- indra/newview/llviewerdisplay.cpp | 2 + 4 files changed, 53 insertions(+), 43 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 110074bdc0..10fdd7c9a9 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1480,7 +1480,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S } BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename, bool defer_copy, LLGLuint* tex_name) - // Call with void data, vmem is allocated but unitialized +// Call with void data, vmem is allocated but unitialized { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; checkActiveThread(); @@ -1505,7 +1505,8 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); - if (main_thread // <--- always force creation of mNewTexName when not on main thread + if (main_thread // <--- always force creation of new_texname when not on main thread ... + && !defer_copy // <--- ... or defer copy is set && mTexName != 0 && discard_level == mCurrentDiscardLevel) { LL_PROFILE_ZONE_NAMED("cglt - early setImage"); @@ -1533,7 +1534,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel - discard_level); } } - + if (tex_name != nullptr) { *tex_name = new_texname; @@ -1568,22 +1569,23 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } //if we're on the image loading thread, be sure to delete old_texname and update mTexName on the main thread - if (!main_thread) + if (!defer_copy) { - if (!defer_copy) + if (!main_thread) { syncToMainThread(new_texname); } - } - else - { - //not on background thread, immediately set mTexName - if (old_texname != 0) + else { - LLImageGL::deleteTextures(1, &old_texname); + //not on background thread, immediately set mTexName + if (old_texname != 0 && old_texname != new_texname) + { + LLImageGL::deleteTextures(1, &old_texname); + } + mTexName = new_texname; } - mTexName = new_texname; } + mTextureMemory = (S32Bytes)getMipBytes(mCurrentDiscardLevel); sGlobalTextureMemory += mTextureMemory; @@ -1596,22 +1598,46 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ return TRUE; } -void update_free_vram() +void LLImageGLThread::updateClass() { LL_PROFILE_ZONE_SCOPED; - if (gGLManager.mHasATIMemInfo) + // update available vram one per second + static LLFrameTimer sTimer; + + if (sTimer.getElapsedSeconds() < 1.f) { - S32 meminfo[4]; - glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo); - LLImageGLThread::sFreeVRAMMegabytes = meminfo[0]; + return; + } + + sTimer.reset(); + + auto func = []() + { + if (gGLManager.mHasATIMemInfo) + { + S32 meminfo[4]; + glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo); + LLImageGLThread::sFreeVRAMMegabytes = meminfo[0]; + } + else if (gGLManager.mHasNVXMemInfo) + { + S32 free_memory; + glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory); + LLImageGLThread::sFreeVRAMMegabytes = free_memory / 1024; + } + }; + + // post update to background thread if available, otherwise execute immediately + auto queue = LLImageGLThread::sEnabled ? LL::WorkQueue::getInstance("LLImageGL") : nullptr; + if (queue) + { + queue->post(func); } - else if (gGLManager.mHasNVXMemInfo) + else { - S32 free_memory; - glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory); - LLImageGLThread::sFreeVRAMMegabytes = free_memory / 1024; + func(); } } @@ -1657,7 +1683,7 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name) LL_PROFILE_ZONE_NAMED("cglt - delete callback"); if (new_tex_name != 0) { - if (mTexName != 0) + if (mTexName != 0 && mTexName != new_tex_name) { LLImageGL::deleteTextures(1, &mTexName); } @@ -1665,17 +1691,6 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name) unref(); } }); - - - //update free vram periodically - static LLFrameTimer timer; - - if (timer.getElapsedTimeF32() > 1.f) //call this once per second. - { - update_free_vram(); - timer.reset(); - } - } BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const @@ -2379,11 +2394,6 @@ void LLImageGLThread::run() S32 LLImageGLThread::getFreeVRAMMegabytes() { - if (!sEnabled) - { - update_free_vram(); - } - return sFreeVRAMMegabytes; } diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 50706890f9..574d83c37e 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -323,6 +323,9 @@ class LLImageGLThread : public LLSimpleton, LL::ThreadPool public: // follows gSavedSettings "RenderGLMultiThreaded" static bool sEnabled; + + // app should call this function periodically + static void updateClass(); // free video memory in megabytes static std::atomic sFreeVRAMMegabytes; diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 7d03cb7609..0a0cfc5cdf 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -1311,11 +1311,6 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI if (main_queue) { //dispatch creation to background thread - LLImageRaw* dst_ptr = dst_image; - LLViewerTexture* bump_ptr = bump; - dst_ptr->ref(); - bump_ptr->ref(); - main_queue->postTo(sTexUpdateQueue, create_texture, gen_normal_map); } else diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 4fc1bdbec3..6a2b06d9b5 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -788,6 +788,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLViewerTexture::updateClass(); } + LLImageGLThread::updateClass(); + { LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_BUMP); gBumpImageList.updateImages(); // must be called before gTextureList version so that it's textures are thrown out first. -- cgit v1.2.3 From 74641a121316a13e106d525fb1684c517791766d Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 22 Feb 2022 19:48:01 -0600 Subject: SL-16815 Cleanup -- disable multithreaded bumpmap generation while tracking down loading issues, fix sync issue in single threaded mode in media textures, restore LL_IMAGEGL_THREAD_CHECK functionality --- indra/llrender/llimagegl.cpp | 2 ++ indra/newview/lldrawpoolbump.cpp | 26 +++++++++++++++++++++++--- indra/newview/llviewermedia.cpp | 11 ++++++++++- 3 files changed, 35 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 10fdd7c9a9..9e26247e1e 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1644,6 +1644,8 @@ void LLImageGLThread::updateClass() void LLImageGL::syncToMainThread(LLGLuint new_tex_name) { LL_PROFILE_ZONE_SCOPED; + llassert(!on_main_thread()); + { LL_PROFILE_ZONE_NAMED("cglt - sync"); if (gGLManager.mHasSync) diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 0a0cfc5cdf..ce4177d1f8 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -76,6 +76,8 @@ static S32 cube_channel = -1; static S32 diffuse_channel = -1; static S32 bump_channel = -1; +#define LL_BUMPLIST_MULTITHREADED 0 + // static void LLStandardBumpmap::init() { @@ -1172,6 +1174,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI { bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA); +#if LL_BUMPLIST_MULTITHREADED auto tex_queue = LLImageGLThread::sEnabled ? sTexUpdateQueue.lock() : nullptr; if (tex_queue) @@ -1188,8 +1191,10 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI bump_ptr->unref(); dst_ptr->unref(); }); + } else +#endif { bump->createGLTexture(0, dst_image); } @@ -1204,22 +1209,34 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI auto* bump_ptr = bump.get(); auto* dst_ptr = dst_image.get(); +#if LL_BUMPLIST_MULTITHREADED bump_ptr->ref(); dst_ptr->ref(); +#endif bump_ptr->setExplicitFormat(GL_RGBA8, GL_ALPHA); auto create_texture = [bump_ptr, dst_ptr]() { +#if LL_IMAGEGL_THREAD_CHECK + bump_ptr->getGLTexture()->mActiveThread = LLThread::currentID(); +#endif LL_PROFILE_ZONE_NAMED("bil - create texture deferred"); bump_ptr->createGLTexture(0, dst_ptr); }; auto gen_normal_map = [bump_ptr, dst_ptr]() { +#if LL_IMAGEGL_THREAD_CHECK + bump_ptr->getGLTexture()->mActiveThread = LLThread::currentID(); +#endif LL_PROFILE_ZONE_NAMED("bil - generate normal map"); if (gNormalMapGenProgram.mProgramObject == 0) { +#if LL_BUMPLIST_MULTITHREADED + bump_ptr->unref(); + dst_ptr->unref(); +#endif return; } gPipeline.mScreen.bindTarget(); @@ -1302,18 +1319,21 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI gNormalMapGenProgram.unbind(); //generateNormalMapFromAlpha(dst_image, nrm_image); - +#if LL_BUMPLIST_MULTITHREADED bump_ptr->unref(); dst_ptr->unref(); +#endif }; - auto main_queue = LLImageGLThread::sEnabled ? sMainQueue.lock() : nullptr; +#if LL_BUMPLIST_MULTITHREADED + auto main_queue = sMainQueue.lock(); - if (main_queue) + if (LLImageGLThread::sEnabled) { //dispatch creation to background thread main_queue->postTo(sTexUpdateQueue, create_texture, gen_normal_map); } else +#endif { create_texture(); gen_normal_map(); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 42bd5d8367..e442afe4b1 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -2911,10 +2911,16 @@ void LLViewerMediaImpl::update() mTexUpdateQueue, // Worker thread queue [=]() // work done on update worker thread { +#if LL_IMAGEGL_THREAD_CHECK + media_tex->getGLTexture()->mActiveThread = LLThread::currentID(); +#endif doMediaTexUpdate(media_tex, data, data_width, data_height, x_pos, y_pos, width, height, true); }, [=]() // callback to main thread { +#if LL_IMAGEGL_THREAD_CHECK + media_tex->getGLTexture()->mActiveThread = LLThread::currentID(); +#endif mTextureUpdatePending = false; media_tex->unref(); unref(); @@ -2991,7 +2997,10 @@ void LLViewerMediaImpl::doMediaTexUpdate(LLViewerMediaTexture* media_tex, U8* da // copy just the subimage covered by the image raw to GL media_tex->setSubImage(data, data_width, data_height, x_pos, y_pos, width, height, tex_name); - media_tex->getGLTexture()->syncToMainThread(tex_name); + if (sync) + { + media_tex->getGLTexture()->syncToMainThread(tex_name); + } // release the data pointer before freeing raw so LLImageRaw destructor doesn't // free memory at data pointer -- cgit v1.2.3 From 8bd71fe6e8a83fe90abf4dfe3d881c2915ce7479 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Wed, 23 Feb 2022 18:38:06 +0200 Subject: SL-16904 FIXED The viewer crashes after trying to empty trash containing calling card --- indra/newview/llinventorybridge.cpp | 5 +++-- indra/newview/llinventorybridge.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 3609c5e457..c1143c9011 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -5762,12 +5762,13 @@ LLCallingCardBridge::LLCallingCardBridge(LLInventoryPanel* inventory, LLItemBridge(inventory, root, uuid) { mObserver = new LLCallingCardObserver(this); - LLAvatarTracker::instance().addParticularFriendObserver(getItem()->getCreatorUUID(), mObserver); + mCreatorUUID = getItem()->getCreatorUUID(); + LLAvatarTracker::instance().addParticularFriendObserver(mCreatorUUID, mObserver); } LLCallingCardBridge::~LLCallingCardBridge() { - LLAvatarTracker::instance().removeParticularFriendObserver(getItem()->getCreatorUUID(), mObserver); + LLAvatarTracker::instance().removeParticularFriendObserver(mCreatorUUID, mObserver); delete mObserver; } diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index c21bfbd02d..0b0ef273e1 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -457,6 +457,7 @@ public: void checkSearchBySuffixChanges(); protected: LLCallingCardObserver* mObserver; + LLUUID mCreatorUUID; }; class LLNotecardBridge : public LLItemBridge -- cgit v1.2.3 From 8ffe3b7b3047381f9c17d0f09757e921ffc246cb Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 23 Feb 2022 16:04:31 -0600 Subject: Fix for mac build --- indra/newview/lldrawpoolbump.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index ce4177d1f8..2b151487fd 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -1216,7 +1216,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI bump_ptr->setExplicitFormat(GL_RGBA8, GL_ALPHA); - auto create_texture = [bump_ptr, dst_ptr]() + auto create_texture = [=]() { #if LL_IMAGEGL_THREAD_CHECK bump_ptr->getGLTexture()->mActiveThread = LLThread::currentID(); @@ -1225,7 +1225,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI bump_ptr->createGLTexture(0, dst_ptr); }; - auto gen_normal_map = [bump_ptr, dst_ptr]() + auto gen_normal_map = [=]() { #if LL_IMAGEGL_THREAD_CHECK bump_ptr->getGLTexture()->mActiveThread = LLThread::currentID(); -- cgit v1.2.3 From d9a68339d5aa18af349e347d6ed74bc01824cec7 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 23 Feb 2022 16:51:33 -0600 Subject: SL-16815 and SL-16906 Avoid redundant bumpmap generation, add some assertions around ref counting and (hack) fix crash on shutdown from dangling texture reference (reduced to 1 dangling texture from several hundred, can't find the remaining reference). --- indra/llcommon/llrefcount.cpp | 5 ++++- indra/llcommon/llrefcount.h | 16 ++++++++++++++-- indra/llrender/llimagegl.cpp | 8 +++++--- indra/newview/lldrawpoolbump.cpp | 4 ++-- indra/newview/llviewertexture.cpp | 3 +-- 5 files changed, 26 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp index 29a5ca6f24..5cbd346411 100644 --- a/indra/llcommon/llrefcount.cpp +++ b/indra/llcommon/llrefcount.cpp @@ -29,6 +29,9 @@ #include "llerror.h" +// maximum reference count before sounding memory leak alarm +const S32 gMaxRefCount = 65536; + LLRefCount::LLRefCount(const LLRefCount& other) : mRef(0) { @@ -47,7 +50,7 @@ LLRefCount::LLRefCount() : LLRefCount::~LLRefCount() { - if (mRef != 0) + if (mRef != LL_REFCOUNT_FREE && mRef != 0) { LL_ERRS() << "deleting non-zero reference" << LL_ENDL; } diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h index 7e4af6ea66..2080da1565 100644 --- a/indra/llcommon/llrefcount.h +++ b/indra/llcommon/llrefcount.h @@ -37,6 +37,10 @@ class LLMutex; // see llthread.h for LLThreadSafeRefCount //---------------------------------------------------------------------------- +//nonsense but recognizable value for freed LLRefCount (aids in debugging) +#define LL_REFCOUNT_FREE 1234567890 +extern const S32 gMaxRefCount; + class LL_COMMON_API LLRefCount { protected: @@ -47,17 +51,25 @@ protected: public: LLRefCount(); + inline void validateRefCount() const + { + llassert(mRef > 0); // ref count below 0, likely corrupted + llassert(mRef < gMaxRefCount); // ref count excessive, likely memory leak + } + inline void ref() const { mRef++; + validateRefCount(); } inline S32 unref() const { - llassert(mRef >= 1); + validateRefCount(); if (0 == --mRef) { - delete this; + mRef = LL_REFCOUNT_FREE; // set to nonsense yet recognizable value to aid in debugging + delete this; return 0; } return mRef; diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 9e26247e1e..5cf3a2a15f 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -437,7 +437,7 @@ LLImageGL::LLImageGL( LLImageGL::~LLImageGL() { - if (!mExternalTexture) + if (!mExternalTexture && gGLManager.mInited) { LLImageGL::cleanup(); sImageList.erase(this); @@ -1629,14 +1629,16 @@ void LLImageGLThread::updateClass() } }; + // post update to background thread if available, otherwise execute immediately - auto queue = LLImageGLThread::sEnabled ? LL::WorkQueue::getInstance("LLImageGL") : nullptr; - if (queue) + auto queue = LL::WorkQueue::getInstance("LLImageGL"); + if (sEnabled) { queue->post(func); } else { + llassert(queue == nullptr); func(); } } diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 2b151487fd..1d5419b515 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -1051,8 +1051,8 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI } } - //if (iter->second->getWidth() != src->getWidth() || - // iter->second->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution + if (iter->second->getWidth() != src->getWidth() || + iter->second->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution { LLPointer dst_image = new LLImageRaw(src->getWidth(), src->getHeight(), 1); U8* dst_data = dst_image->getData(); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index fa2c070ea0..e3ac56d0d3 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1619,7 +1619,6 @@ void LLViewerFetchedTexture::scheduleCreateTexture() mNeedsCreateTexture = TRUE; if (preCreateTexture()) { - ref(); #if LL_IMAGEGL_THREAD_CHECK //grab a copy of the raw image data to make sure it isn't modified pending texture creation U8* data = mRawImage->getData(); @@ -1635,6 +1634,7 @@ void LLViewerFetchedTexture::scheduleCreateTexture() auto mainq = LLImageGLThread::sEnabled ? mMainQueue.lock() : nullptr; if (mainq) { + ref(); mainq->postTo( mImageQueue, // work to be done on LLImageGL worker thread @@ -1681,7 +1681,6 @@ void LLViewerFetchedTexture::scheduleCreateTexture() else { gTextureList.mCreateTextureList.insert(this); - unref(); } } } -- cgit v1.2.3 From fc0b238654091c6090d5d85ceda51fbc6cb71eaa Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 23 Feb 2022 17:55:44 -0600 Subject: Fix for media textures failing to update (and eating lots of memory) on Mac/Intel --- indra/llrender/llimagegl.cpp | 23 ++++++++++++++--------- indra/llrender/llimagegl.h | 3 +++ indra/newview/llviewermedia.cpp | 5 +++++ 3 files changed, 22 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 5cf3a2a15f..63f9a67e2c 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1685,18 +1685,23 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name) [=]() { LL_PROFILE_ZONE_NAMED("cglt - delete callback"); - if (new_tex_name != 0) - { - if (mTexName != 0 && mTexName != new_tex_name) - { - LLImageGL::deleteTextures(1, &mTexName); - } - mTexName = new_tex_name; - unref(); - } + syncTexName(new_tex_name); + unref(); }); } +void LLImageGL::syncTexName(LLGLuint texname) +{ + if (texname != 0) + { + if (mTexName != 0 && mTexName != texname) + { + LLImageGL::deleteTextures(1, &mTexName); + } + mTexName = texname; + } +} + BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const { llassert_always(sAllowReadBackRaw) ; diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 574d83c37e..4d5b60d6bc 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -304,6 +304,9 @@ public: void setTexName(GLuint texName) { mTexName = texName; } + //similar to setTexName, but will call deleteTextures on mTexName if mTexName is not 0 or texname + void syncTexName(LLGLuint texname); + //for debug use: show texture size distribution //---------------------------------------- static S32 sCurTexSizeBar ; diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index e442afe4b1..272da6367b 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -2997,10 +2997,15 @@ void LLViewerMediaImpl::doMediaTexUpdate(LLViewerMediaTexture* media_tex, U8* da // copy just the subimage covered by the image raw to GL media_tex->setSubImage(data, data_width, data_height, x_pos, y_pos, width, height, tex_name); + if (sync) { media_tex->getGLTexture()->syncToMainThread(tex_name); } + else + { + media_tex->getGLTexture()->syncTexName(tex_name); + } // release the data pointer before freeing raw so LLImageRaw destructor doesn't // free memory at data pointer -- cgit v1.2.3 From 4f9fa5e817c44d2ba0bc5558955085f48b280861 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 23 Feb 2022 19:53:49 -0600 Subject: Fix for some GPUs thinking they have 0 available vram. --- indra/llrender/llimagegl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 63f9a67e2c..230d2b3dd0 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -2372,7 +2372,7 @@ void LLImageGL::checkActiveThread() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, nummips); */ -std::atomic LLImageGLThread::sFreeVRAMMegabytes; +std::atomic LLImageGLThread::sFreeVRAMMegabytes = 4096; //if free vram is unknown, default to 4GB LLImageGLThread::LLImageGLThread(LLWindow* window) // We want exactly one thread, but a very large capacity: we never want -- cgit v1.2.3 From 85e480616de4e741f9f34a396677002d86a1d660 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 23 Feb 2022 19:59:46 -0600 Subject: Fix for mac build --- indra/llrender/llimagegl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 230d2b3dd0..f43671dee5 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -2372,7 +2372,7 @@ void LLImageGL::checkActiveThread() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, nummips); */ -std::atomic LLImageGLThread::sFreeVRAMMegabytes = 4096; //if free vram is unknown, default to 4GB +std::atomic LLImageGLThread::sFreeVRAMMegabytes(4096); //if free vram is unknown, default to 4GB LLImageGLThread::LLImageGLThread(LLWindow* window) // We want exactly one thread, but a very large capacity: we never want -- cgit v1.2.3 From 1af45ee1dfdda1e6408e5f9b3fdeee9a2647bfd0 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Thu, 24 Feb 2022 13:04:09 +0200 Subject: SL-16921 FIXED Viewer crashes on disconnect if 'About land' floater is opened --- indra/newview/llviewerparcelmgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 56370df751..e69b0347f8 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -878,7 +878,7 @@ LLParcel* LLViewerParcelMgr::getCollisionParcel() const void LLViewerParcelMgr::render() { - if (mSelected && mRenderSelection && gSavedSettings.getBOOL("RenderParcelSelection")) + if (mSelected && mRenderSelection && gSavedSettings.getBOOL("RenderParcelSelection") && !gDisconnected) { // Rendering is done in agent-coordinates, so need to supply // an appropriate offset to the render code. -- cgit v1.2.3 From 21baea0907027c655c5170975c0ea669430c9c40 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 24 Feb 2022 00:35:00 +0200 Subject: SL-3787 Fixed mesh uploader LoD generation returning worse results than higher lod --- indra/newview/llmodelpreview.cpp | 61 +++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 5d81d2c9b3..9e5a31d71e 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -1759,19 +1759,15 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d { genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, true); } - - LL_INFOS() << "Model " << target_model->getName() - << " lod " << which_lod - << " simplified using per face method." << LL_ENDL; } if (model_meshopt_mode == MESH_OPTIMIZER_AUTO) { - // Switches between 'combine' method and 'per model sloppy' based on combine's result. + // Switches between 'combine' method and 'sloppy' based on combine's result. F32 allowed_ratio_drift = 2.f; - F32 res_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); - - if (res_ratio < 0) + F32 precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); + + if (precise_ratio < 0) { // U16 vertices overflow, shouldn't happen, but just in case for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx) @@ -1779,42 +1775,72 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, false); } } - else if (res_ratio * allowed_ratio_drift < indices_decimator) + else if (precise_ratio * allowed_ratio_drift < indices_decimator) { // Try sloppy variant if normal one failed to simplify model enough. - res_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, true); + // Sloppy variant can fail entirely and has issues with precision, + // so code needs to do multiple attempts with different decimators. + // Todo: this is a bit of a mess, needs to be refined and improved + F32 last_working_decimator = 0.f; + F32 last_working_ratio = F32_MAX; + + F32 sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, true); + + if (sloppy_ratio > 0) + { + // Would be better to do a copy of target_model here, but if + // we need to use sloppy decimation, model should be cheap + // and fast to generate and it won't affect end result + last_working_decimator = indices_decimator; + last_working_ratio = sloppy_ratio; + } // Sloppy has a tendecy to error into lower side, so a request for 100 // triangles turns into ~70, so check for significant difference from target decimation F32 sloppy_ratio_drift = 1.4f; if (lod_mode == LIMIT_TRIANGLES - && (res_ratio > indices_decimator * sloppy_ratio_drift || res_ratio < 0)) + && (sloppy_ratio > indices_decimator * sloppy_ratio_drift || sloppy_ratio < 0)) { // Apply a correction to compensate. // (indices_decimator / res_ratio) by itself is likely to overshoot to a differend // side due to overal lack of precision, and we don't need an ideal result, which // likely does not exist, just a better one, so a partial correction is enough. - F32 sloppy_decimator = indices_decimator * (indices_decimator / res_ratio + 1) / 2; - res_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, true); + F32 sloppy_decimator = indices_decimator * (indices_decimator / sloppy_ratio + 1) / 2; + sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, true); } + if (last_working_decimator > 0 && sloppy_ratio < last_working_ratio) + { + // Compensation didn't work, return back to previous decimator + sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, true); + } + + if (sloppy_ratio < 0) + { + // sloppy method didn't work, final attempt with lower decimation + F32 sloppy_decimator = indices_decimator / decimation; + sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, true); + } - if (res_ratio < 0) + if (sloppy_ratio < 0 || sloppy_ratio < precise_ratio) { - // Sloppy variant failed to generate triangles. + // Sloppy variant failed to generate triangles or is worse. // Can happen with models that are too simple as is. - // Fallback to normal method or use lower decimator. - genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); + // Fallback to normal method + + precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); LL_INFOS() << "Model " << target_model->getName() << " lod " << which_lod + << " resulting ratio " << precise_ratio << " simplified using per model method." << LL_ENDL; } else { LL_INFOS() << "Model " << target_model->getName() << " lod " << which_lod + << " resulting ratio " << sloppy_ratio << " sloppily simplified using per model method." << LL_ENDL; } } @@ -1822,6 +1848,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d { LL_INFOS() << "Model " << target_model->getName() << " lod " << which_lod + << " resulting ratio " << precise_ratio << " simplified using per model method." << LL_ENDL; } } -- cgit v1.2.3 From 658a30bd2e116149d3e6e6f937f9ad7f14983ce3 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 24 Feb 2022 13:04:40 -0600 Subject: SL-16907 Potential fix for crash in updateSkinInfoMatrixPalette --- indra/newview/lldrawpoolalpha.cpp | 2 +- indra/newview/llspatialpartition.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 963ea6ff8b..2bf8e9b911 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -795,7 +795,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) bool LLDrawPoolAlpha::uploadMatrixPalette(const LLDrawInfo& params) { - const LLVOAvatar::MatrixPaletteCache& mpc = params.mAvatar->updateSkinInfoMatrixPalette(params.mSkinInfo); + const LLVOAvatar::MatrixPaletteCache& mpc = params.mAvatar.get()->updateSkinInfoMatrixPalette(params.mSkinInfo); U32 count = mpc.mMatrixPalette.size(); if (count == 0) diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index eefb5b0eba..acfcd63686 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -40,6 +40,8 @@ #include "llface.h" #include "llviewercamera.h" #include "llvector4a.h" +#include "llvoavatar.h" + #include #include @@ -125,7 +127,7 @@ public: F32 mAlphaMaskCutoff; U8 mDiffuseAlphaMode; bool mSelected; - LLVOAvatar* mAvatar = nullptr; + LLPointer mAvatar = nullptr; LLMeshSkinInfo* mSkinInfo = nullptr; -- cgit v1.2.3 From c141ecdcc2f074145b0a25087396be73a2e5ce7a Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 25 Feb 2022 13:36:35 +0200 Subject: SL-3787 Fixed sloppy mode returning invalid model In automatic mode for simple models gradualy increase sloppy decimator until something valid is found. --- indra/newview/llmodelpreview.cpp | 41 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 9e5a31d71e..6bbe27d101 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -1757,7 +1757,11 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d // Run meshoptimizer for each face for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx) { - genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, true); + if (genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, true) < 0) + { + // Sloppy failed and returned an invalid model + genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, false); + } } } @@ -1818,9 +1822,38 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d if (sloppy_ratio < 0) { - // sloppy method didn't work, final attempt with lower decimation - F32 sloppy_decimator = indices_decimator / decimation; - sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, true); + // Sloppy method didn't work, try with smaller decimation values + S32 size_vertices = 0; + + for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx) + { + const LLVolumeFace &face = base->getVolumeFace(face_idx); + size_vertices += face.mNumVertices; + } + + // Complex models aren't supposed to get here, they are supposed + // to work on a first try of sloppy due to having more viggle room. + // If they didn't, something is likely wrong, no point locking the + // thread in a long calculation that will fail. + const U32 too_many_vertices = 27000; + if (size_vertices > too_many_vertices) + { + LL_WARNS() << "Sloppy optimization method failed for a complex model " << target_model->getName() << LL_ENDL; + } + else + { + // Find a decimator that does work + F32 sloppy_decimation_step = sqrt((F32)decimation); // example: 27->15->9->5->3 + F32 sloppy_decimator = indices_decimator / sloppy_decimation_step; + + while (sloppy_ratio < 0 + && sloppy_decimator > precise_ratio + && sloppy_decimator > 1)// precise_ratio isn't supposed to be below 1, but check just in case + { + sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, true); + sloppy_decimator = sloppy_decimator / sloppy_decimation_step; + } + } } if (sloppy_ratio < 0 || sloppy_ratio < precise_ratio) -- cgit v1.2.3 From 92c302d6fba687f0921544b278e22b698d058646 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 25 Feb 2022 13:36:35 +0200 Subject: SL-15940 Verify triangle limit to not trigger an assert inside meshoptimizer --- indra/newview/llmodelpreview.cpp | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 6bbe27d101..58cf2e4ab2 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -1299,6 +1299,11 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe size_vertices += face.mNumVertices; } + if (size_indices < 3) + { + return -1; + } + // Allocate buffers, note that we are using U32 buffer instead of U16 U32* combined_indices = (U32*)ll_aligned_malloc_32(size_indices * sizeof(U32)); U32* output_indices = (U32*)ll_aligned_malloc_32(size_indices * sizeof(U32)); @@ -1343,10 +1348,10 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe // Now that we have buffers, optimize S32 target_indices = 0; - F32 result_code = 0; // how far from original the model is, 1 == 100% + F32 result_error = 0; // how far from original the model is, 1 == 100% S32 new_indices = 0; - target_indices = llmax(3, llfloor(size_indices / indices_decimator)); // leave at least one triangle + target_indices = llclamp(llfloor(size_indices / indices_decimator), 3, (S32)size_indices); // leave at least one triangle new_indices = LLMeshOptimizer::simplifyU32( output_indices, combined_indices, @@ -1357,17 +1362,27 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe target_indices, error_threshold, sloppy, - &result_code); + &result_error); - if (result_code < 0) + if (result_error < 0) { - LL_WARNS() << "Negative result code from meshoptimizer for model " << target_model->mLabel + LL_WARNS() << "Negative result error from meshoptimizer for model " << target_model->mLabel << " target Indices: " << target_indices << " new Indices: " << new_indices << " original count: " << size_indices << LL_ENDL; } + if (new_indices < 3) + { + // Model should have at least one visible triangle + ll_aligned_free<64>(combined_positions); + ll_aligned_free_32(output_indices); + ll_aligned_free_32(combined_indices); + + return -1; + } + // repack back into individual faces LLVector4a* buffer_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 2 * size_vertices + tc_bytes_size); @@ -1520,16 +1535,20 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target { const LLVolumeFace &face = base_model->getVolumeFace(face_idx); S32 size_indices = face.mNumIndices; + if (size_indices < 3) + { + return -1; + } // todo: do not allocate per each face, add one large buffer somewhere // faces have limited amount of indices S32 size = (size_indices * sizeof(U16) + 0xF) & ~0xF; U16* output = (U16*)ll_aligned_malloc_16(size); S32 target_indices = 0; - F32 result_code = 0; // how far from original the model is, 1 == 100% + F32 result_error = 0; // how far from original the model is, 1 == 100% S32 new_indices = 0; - target_indices = llmax(3, llfloor(size_indices / indices_decimator)); // leave at least one triangle + target_indices = llclamp(llfloor(size_indices / indices_decimator), 3, (S32)size_indices); // leave at least one triangle new_indices = LLMeshOptimizer::simplify( output, face.mIndices, @@ -1540,12 +1559,12 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target target_indices, error_threshold, sloppy, - &result_code); + &result_error); - if (result_code < 0) + if (result_error < 0) { - LL_WARNS() << "Negative result code from meshoptimizer for face " << face_idx + LL_WARNS() << "Negative result error from meshoptimizer for face " << face_idx << " of model " << target_model->mLabel << " target Indices: " << target_indices << " new Indices: " << new_indices -- cgit v1.2.3