From ab87978cbc71cd4c83648627998055a010700f05 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 27 Jun 2024 13:12:43 -0500 Subject: 1836 dont store texture in system memory unless absolutely necessary (#1843) * #1836 Texture memory usage overhaul. Much decrufting - don't keep a copy of textures in system memory - use GPU to downrez textures instead of reloading from cache - use GPU to generate brightness/darkness bumpmaps --- indra/llrender/llgltexture.cpp | 21 ---- indra/llrender/llgltexture.h | 6 +- indra/llrender/llimagegl.cpp | 260 ++++++++++++++--------------------------- indra/llrender/llimagegl.h | 35 +++--- 4 files changed, 109 insertions(+), 213 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp index e614f45986..4dcca5a726 100644 --- a/indra/llrender/llgltexture.cpp +++ b/indra/llrender/llgltexture.cpp @@ -351,20 +351,6 @@ void LLGLTexture::forceUpdateBindStats(void) const return mGLTexturep->forceUpdateBindStats() ; } -U32 LLGLTexture::getTexelsInAtlas() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getTexelsInAtlas() ; -} - -U32 LLGLTexture::getTexelsInGLTexture() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getTexelsInGLTexture() ; -} - bool LLGLTexture::isGLTextureCreated() const { llassert(mGLTexturep.notNull()) ; @@ -372,13 +358,6 @@ bool LLGLTexture::isGLTextureCreated() const return mGLTexturep->isGLTextureCreated() ; } -S32 LLGLTexture::getDiscardLevelInAtlas() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getDiscardLevelInAtlas() ; -} - void LLGLTexture::destroyGLTexture() { if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture()) diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h index 0901243f8f..a7de20dc5c 100644 --- a/indra/llrender/llgltexture.h +++ b/indra/llrender/llgltexture.h @@ -51,10 +51,10 @@ public: BOOST_NONE = 0, BOOST_AVATAR , BOOST_AVATAR_BAKED , - BOOST_SCULPTED , BOOST_TERRAIN , // Needed for minimap generation for now. Lower than BOOST_HIGH so the texture stats don't get forced, i.e. texture stats are manually managed by minimap/terrain instead. BOOST_HIGH = 10, + BOOST_SCULPTED , BOOST_BUMP , BOOST_UNUSED_1 , // Placeholder to avoid disrupting habits around texture debug BOOST_SELECTED , @@ -75,7 +75,6 @@ public: AVATAR_SCRATCH_TEX, DYNAMIC_TEX, MEDIA, - ATLAS, OTHER, MAX_GL_IMAGE_CATEGORY }; @@ -156,10 +155,7 @@ public: bool isJustBound()const ; void forceUpdateBindStats(void) const; - U32 getTexelsInAtlas() const ; - U32 getTexelsInGLTexture() const ; bool isGLTextureCreated() const ; - S32 getDiscardLevelInAtlas() const ; LLGLTextureState getTextureState() const { return mTextureState; } //--------------------------------------------------------------------------------------------- diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 7e5cd628c1..956bcef352 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -41,6 +41,7 @@ #include "llrender.h" #include "llwindow.h" #include "llframetimer.h" +#include extern LL_COMMON_API bool on_main_thread(); @@ -130,10 +131,9 @@ S32 LLImageGL::sCount = 0; bool LLImageGL::sGlobalUseAnisotropic = false; F32 LLImageGL::sLastFrameTime = 0.f; -bool LLImageGL::sAllowReadBackRaw = false ; LLImageGL* LLImageGL::sDefaultGLTexture = NULL ; bool LLImageGL::sCompressTextures = false; -std::set LLImageGL::sImageList; +std::unordered_set LLImageGL::sImageList; bool LLImageGLThread::sEnabledTextures = false; @@ -150,6 +150,9 @@ S32 LLImageGL::sMaxCategories = 1 ; //optimization for when we don't need to calculate mIsMask bool LLImageGL::sSkipAnalyzeAlpha; +U32 LLImageGL::sScratchPBO = 0; +U32 LLImageGL::sScratchPBOSize = 0; + //------------------------ //**************************************************************************************************** @@ -159,20 +162,6 @@ bool LLImageGL::sSkipAnalyzeAlpha; //************************************************************************************** //below are functions for debug use //do not delete them even though they are not currently being used. -void check_all_images() -{ - for (std::set::iterator iter = LLImageGL::sImageList.begin(); - iter != LLImageGL::sImageList.end(); iter++) - { - LLImageGL* glimage = *iter; - if (glimage->getTexName() && glimage->isGLTextureCreated()) - { - gGL.getTexUnit(0)->bind(glimage) ; - glimage->checkTexSize() ; - gGL.getTexUnit(0)->unbind(glimage->getTarget()) ; - } - } -} void LLImageGL::checkTexSize(bool forced) const { @@ -252,6 +241,11 @@ void LLImageGL::initClass(LLWindow* window, S32 num_catagories, bool skip_analyz LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; sSkipAnalyzeAlpha = skip_analyze_alpha; + if (sScratchPBO == 0) + { + glGenBuffers(1, &sScratchPBO); + } + if (thread_texture_loads || thread_media_updates) { LLImageGLThread::createInstance(window); @@ -265,6 +259,12 @@ void LLImageGL::cleanupClass() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; LLImageGLThread::deleteSingleton(); + if (sScratchPBO != 0) + { + glDeleteBuffers(1, &sScratchPBO); + sScratchPBO = 0; + sScratchPBOSize = 0; + } } @@ -360,66 +360,19 @@ void LLImageGL::updateStats(F32 current_time) //---------------------------------------------------------------------------- //static -void LLImageGL::destroyGL(bool save_state) +void LLImageGL::destroyGL() { for (S32 stage = 0; stage < gGLManager.mNumTextureImageUnits; stage++) { gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE); } - - sAllowReadBackRaw = true ; - for (std::set::iterator iter = sImageList.begin(); - iter != sImageList.end(); iter++) - { - LLImageGL* glimage = *iter; - if (glimage->mTexName) - { - if (save_state && glimage->isGLTextureCreated() && glimage->mComponents) - { - glimage->mSaveData = new LLImageRaw; - if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false)) //necessary, keep it. - { - glimage->mSaveData = NULL ; - } - } - - glimage->destroyGLTexture(); - stop_glerror(); - } - } - sAllowReadBackRaw = false ; -} - -//static -void LLImageGL::restoreGL() -{ - for (std::set::iterator iter = sImageList.begin(); - iter != sImageList.end(); iter++) - { - LLImageGL* glimage = *iter; - if(glimage->getTexName()) - { - LL_ERRS() << "tex name is not 0." << LL_ENDL ; - } - if (glimage->mSaveData.notNull()) - { - if (glimage->getComponents() && glimage->mSaveData->getComponents()) - { - glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData, 0, true, glimage->getCategory()); - stop_glerror(); - } - glimage->mSaveData = NULL; // deletes data - } - } } //static void LLImageGL::dirtyTexOptions() { - for (std::set::iterator iter = sImageList.begin(); - iter != sImageList.end(); iter++) + for (auto& glimage : sImageList) { - LLImageGL* glimage = *iter; glimage->mTexOptionsDirty = true; stop_glerror(); } @@ -542,10 +495,6 @@ void LLImageGL::init(bool usemipmaps) mHeight = 0; mCurrentDiscardLevel = -1; - mDiscardLevelInAtlas = -1 ; - mTexelsInAtlas = 0 ; - mTexelsInGLTexture = 0 ; - mAllowCompression = true; mTarget = GL_TEXTURE_2D; @@ -622,9 +571,6 @@ bool LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_leve return false; } - // pickmask validity depends on old image size, delete it - freePickMask(); - mWidth = width; mHeight = height; mComponents = ncomponents; @@ -1025,98 +971,6 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 return true; } -bool LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image) -{ - //not compatible with core GL profile - llassert(!LLRender::sGLCoreProfile); - - if (gGLManager.mIsDisabled) - { - LL_WARNS() << "Trying to create a texture while GL is disabled!" << LL_ENDL; - return false; - } - llassert(gGLManager.mInited); - stop_glerror(); - - if (discard_level < 0) - { - llassert(mCurrentDiscardLevel >= 0); - discard_level = mCurrentDiscardLevel; - } - - // Actual image width/height = raw image width/height * 2^discard_level - S32 w = raw_image->getWidth() << discard_level; - S32 h = raw_image->getHeight() << discard_level; - - // setSize may call destroyGLTexture if the size does not match - if (!setSize(w, h, raw_image->getComponents(), discard_level)) - { - LL_WARNS() << "Trying to create a texture with incorrect dimensions!" << LL_ENDL; - return false; - } - - if (!mHasExplicitFormat) - { - switch (mComponents) - { - case 1: - // Use luminance alpha (for fonts) - mFormatInternal = GL_LUMINANCE8; - mFormatPrimary = GL_LUMINANCE; - mFormatType = GL_UNSIGNED_BYTE; - break; - case 2: - // Use luminance alpha (for fonts) - mFormatInternal = GL_LUMINANCE8_ALPHA8; - mFormatPrimary = GL_LUMINANCE_ALPHA; - mFormatType = GL_UNSIGNED_BYTE; - break; - case 3: - mFormatInternal = GL_RGB8; - mFormatPrimary = GL_RGB; - mFormatType = GL_UNSIGNED_BYTE; - break; - case 4: - mFormatInternal = GL_RGBA8; - mFormatPrimary = GL_RGBA; - mFormatType = GL_UNSIGNED_BYTE; - break; - default: - LL_ERRS() << "Bad number of components for texture: " << (U32) getComponents() << LL_ENDL; - } - } - - mCurrentDiscardLevel = discard_level; - mDiscardLevelInAtlas = discard_level; - mTexelsInAtlas = raw_image->getWidth() * raw_image->getHeight() ; - mLastBindTime = sLastFrameTime; - mGLTextureCreated = false ; - - glPixelStorei(GL_UNPACK_ROW_LENGTH, raw_image->getWidth()); - stop_glerror(); - - if(mFormatSwapBytes) - { - glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); - stop_glerror(); - } - - return true ; -} - -void LLImageGL::postAddToAtlas() -{ - if(mFormatSwapBytes) - { - glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); - stop_glerror(); - } - - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption); - stop_glerror(); -} - U32 type_width_from_pixtype(U32 pixtype) { U32 type_width = 0; @@ -1752,7 +1606,6 @@ bool LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, bool data_ mTextureMemory = (S64Bytes)getMipBytes(mCurrentDiscardLevel); - mTexelsInGLTexture = getWidth() * getHeight(); // mark this as bound at this point, so we don't throw it out immediately mLastBindTime = sLastFrameTime; @@ -1830,8 +1683,7 @@ void LLImageGL::syncTexName(LLGLuint texname) bool LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const { - llassert_always(sAllowReadBackRaw) ; - //LL_ERRS() << "should not call this function!" << LL_ENDL ; + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if (discard_level < 0) { @@ -2297,6 +2149,8 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) //---------------------------------------------------------------------------- U32 LLImageGL::createPickMask(S32 pWidth, S32 pHeight) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + freePickMask(); U32 pick_width = pWidth/2 + 1; U32 pick_height = pHeight/2 + 1; @@ -2314,7 +2168,6 @@ U32 LLImageGL::createPickMask(S32 pWidth, S32 pHeight) //---------------------------------------------------------------------------- void LLImageGL::freePickMask() { - // pickmask validity depends on old image size, delete it if (mPickMask != NULL) { delete [] mPickMask; @@ -2352,16 +2205,16 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) return ; } - freePickMask(); - if (mFormatType != GL_UNSIGNED_BYTE || ((mFormatPrimary != GL_RGBA) && (mFormatPrimary != GL_SRGB_ALPHA))) { //cannot generate a pick mask for this texture + freePickMask(); return; } + #ifdef SHOW_ASSERT const U32 pickSize = createPickMask(width, height); #else // SHOW_ASSERT @@ -2460,6 +2313,73 @@ void LLImageGL::resetCurTexSizebar() sCurTexSizeBar = -1 ; sCurTexPickSize = -1 ; } + +bool LLImageGL::scaleDown(S32 desired_discard) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + + if (mTarget != GL_TEXTURE_2D) + { + return false; + } + + desired_discard = llmin(desired_discard, mMaxDiscardLevel); + + if (desired_discard <= mCurrentDiscardLevel) + { + return false; + } + + S32 mip = desired_discard - mCurrentDiscardLevel; + + S32 desired_width = getWidth(desired_discard); + S32 desired_height = getHeight(desired_discard); + + U64 size = getBytes(desired_discard); + llassert(size <= 2048*2048*4); // we shouldn't be using this method to downscale huge textures, but it'll work + gGL.getTexUnit(0)->bind(this); + + + if (sScratchPBO == 0) + { + glGenBuffers(1, &sScratchPBO); + sScratchPBOSize = 0; + } + + glBindBuffer(GL_PIXEL_PACK_BUFFER, sScratchPBO); + + if (size > sScratchPBOSize) + { + glBufferData(GL_PIXEL_PACK_BUFFER, size, NULL, GL_STREAM_COPY); + sScratchPBOSize = size; + } + + glGetTexImage(mTarget, mip, mFormatPrimary, mFormatType, nullptr); + + free_tex_image(mTexName); + + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, sScratchPBO); + glTexImage2D(mTarget, 0, mFormatPrimary, desired_width, desired_height, 0, mFormatPrimary, mFormatType, nullptr); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + alloc_tex_image(desired_width, desired_height, mFormatPrimary); + + if (mHasMipMaps) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glGenerateMipmap"); + glGenerateMipmap(mTarget); + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + mCurrentDiscardLevel = desired_discard; + + return true; +} + + //---------------------------------------------------------------------------- #if LL_IMAGEGL_THREAD_CHECK void LLImageGL::checkActiveThread() diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 5c7a5ce821..3892e9c014 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -39,6 +39,7 @@ #include "llrender.h" #include "threadpool.h" #include "workqueue.h" +#include #define LL_IMAGEGL_THREAD_CHECK 0 //set to 1 to enable thread debugging for ImageGL @@ -83,9 +84,8 @@ public: // needs to be called every frame static void updateStats(F32 current_time); - // Save off / restore GL textures - static void destroyGL(bool save_state = true); - static void restoreGL(); + // cleanup GL state + static void destroyGL(); static void dirtyTexOptions(); static bool checkSize(S32 width, S32 height); @@ -148,6 +148,10 @@ public: S32 getDiscardLevel() const { return mCurrentDiscardLevel; } S32 getMaxDiscardLevel() const { return mMaxDiscardLevel; } + // override the current discard level + // should only be used for local textures where you know exactly what you're doing + void setDiscardLevel(S32 level) { mCurrentDiscardLevel = level; } + S32 getCurrentWidth() const { return mWidth ;} S32 getCurrentHeight() const { return mHeight ;} S32 getWidth(S32 discard_level = -1) const; @@ -194,26 +198,26 @@ public: void setFilteringOption(LLTexUnit::eTextureFilterOptions option); LLTexUnit::eTextureFilterOptions getFilteringOption(void) const { return mFilterOption; } - LLGLenum getTexTarget()const { return mTarget ;} - S8 getDiscardLevelInAtlas()const {return mDiscardLevelInAtlas;} - U32 getTexelsInAtlas()const { return mTexelsInAtlas ;} - U32 getTexelsInGLTexture()const {return mTexelsInGLTexture;} - + LLGLenum getTexTarget()const { return mTarget; } void init(bool usemipmaps); virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors void setNeedsAlphaAndPickMask(bool need_mask); - bool preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image); - void postAddToAtlas() ; - #if LL_IMAGEGL_THREAD_CHECK // thread debugging std::thread::id mActiveThread; void checkActiveThread(); #endif + // scale down to the desired discard level using GPU + // returns true if texture was scaled down + // desired discard will be clamped to max discard + // if desired discard is less than or equal to current discard, no scaling will occur + // only works for GL_TEXTURE_2D target + bool scaleDown(S32 desired_discard); + public: // Various GL/Rendering options S64Bytes mTextureMemory; @@ -240,15 +244,10 @@ private: bool mGLTextureCreated ; LLGLuint mTexName; - //LLGLuint mNewTexName = 0; // tex name set by background thread to be applied in main thread U16 mWidth; U16 mHeight; S8 mCurrentDiscardLevel; - S8 mDiscardLevelInAtlas; - U32 mTexelsInAtlas ; - U32 mTexelsInGLTexture; - bool mAllowCompression; protected: @@ -275,7 +274,7 @@ protected: // STATICS public: - static std::set sImageList; + static std::unordered_set sImageList; static S32 sCount; static F32 sLastFrameTime; @@ -301,6 +300,8 @@ public: private: static S32 sMaxCategories; static bool sSkipAnalyzeAlpha; + static U32 sScratchPBO; + static U32 sScratchPBOSize; //the flag to allow to call readBackRaw(...). //can be removed if we do not use that function at all. -- cgit v1.2.3 From 08b933a0c67463f06f124420f16c8a3f7dc83f1f Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 3 Jul 2024 17:42:24 -0500 Subject: #1870 Tune up for better experience on integrated intel with low memory (#1872) * More deterministic vsize calculation. Add control for choosing downscale method. * Quick hack to make GLTF preview work again --- indra/llrender/llgl.h | 3 + indra/llrender/llimagegl.cpp | 126 +++++++++++++++++++++++++++++--------- indra/llrender/llimagegl.h | 5 +- indra/llrender/llrender.h | 6 +- indra/llrender/llrendertarget.cpp | 12 +++- indra/llrender/llrendertarget.h | 4 +- 6 files changed, 120 insertions(+), 36 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 909dad2e85..be1c0a532a 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -102,6 +102,9 @@ public: bool mIsNVIDIA; bool mIsIntel; + // hints to the render pipe + U32 mDownScaleMethod = 0; // see settings.xml RenderDownScaleMethod + #if LL_DARWIN // Needed to distinguish problem cards on older Macs that break with Materials bool mIsMobileGF; diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 956bcef352..34200ef5cb 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -57,6 +57,9 @@ const F32 MIN_TEXTURE_LIFETIME = 10.f; U32 wpo2(U32 i); +U32 LLImageGL::sFrameCount = 0; + + // texture memory accounting (for macOS) static LLMutex sTexMemMutex; static std::unordered_map sTextureAllocs; @@ -1003,7 +1006,7 @@ bool should_stagger_image_set(bool compressed) #else // glTexSubImage2D doesn't work with compressed textures on select tested Nvidia GPUs on Windows 10 -Cosmic,2023-03-08 // Setting media textures off-thread seems faster when not using sub_image_lines (Nvidia/Windows 10) -Cosmic,2023-03-31 - return !compressed && on_main_thread(); + return !compressed && on_main_thread() && !gGLManager.mIsIntel; #endif } @@ -1185,13 +1188,37 @@ void LLImageGL::generateTextures(S32 numTextures, U32 *textures) } } +// static +void LLImageGL::updateClass() +{ + sFrameCount++; +} + // static void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures) { + // wait a few frames before actually deleting the textures to avoid + // synchronization issues with the GPU + static std::vector sFreeList[4]; + if (gGLManager.mInited) { - free_tex_images(numTextures, textures); - glDeleteTextures(numTextures, textures); + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + U32 idx = sFrameCount % 4; + + for (S32 i = 0; i < numTextures; ++i) + { + sFreeList[idx].push_back(textures[i]); + } + + idx = (sFrameCount + 3) % 4; + + if (!sFreeList[idx].empty()) + { + glDeleteTextures((GLsizei) sFreeList[idx].size(), sFreeList[idx].data()); + free_tex_images((GLsizei) sFreeList[idx].size(), sFreeList[idx].data()); + sFreeList[idx].resize(0); + } } } @@ -2335,44 +2362,85 @@ bool LLImageGL::scaleDown(S32 desired_discard) S32 desired_width = getWidth(desired_discard); S32 desired_height = getHeight(desired_discard); - U64 size = getBytes(desired_discard); - llassert(size <= 2048*2048*4); // we shouldn't be using this method to downscale huge textures, but it'll work - gGL.getTexUnit(0)->bind(this); + if (gGLManager.mDownScaleMethod == 0) + { // use an FBO to downscale the texture + // allocate new texture + U32 temp_texname = 0; + generateTextures(1, &temp_texname); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, temp_texname, true); + { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glTexImage2D"); + glTexImage2D(mTarget, 0, mFormatPrimary, desired_width, desired_height, 0, mFormatPrimary, mFormatType, NULL); + } + // account for new texture getting created + alloc_tex_image(desired_width, desired_height, mFormatPrimary); - if (sScratchPBO == 0) - { - glGenBuffers(1, &sScratchPBO); - sScratchPBOSize = 0; - } + // Use render-to-texture to scale down the texture + { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glFramebufferTexture2D"); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTarget, temp_texname, 0); + } - glBindBuffer(GL_PIXEL_PACK_BUFFER, sScratchPBO); + glViewport(0, 0, desired_width, desired_height); - if (size > sScratchPBOSize) - { - glBufferData(GL_PIXEL_PACK_BUFFER, size, NULL, GL_STREAM_COPY); - sScratchPBOSize = size; + // draw a full screen triangle + gGL.getTexUnit(0)->bind(this); + glDrawArrays(GL_TRIANGLES, 0, 3); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + // delete old texture and assign new texture name + deleteTextures(1, &mTexName); + mTexName = temp_texname; + + if (mHasMipMaps) + { // generate mipmaps if needed + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glGenerateMipmap"); + gGL.getTexUnit(0)->bind(this); + glGenerateMipmap(mTarget); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } } + else + { // use a PBO to downscale the texture + U64 size = getBytes(desired_discard); + llassert(size <= 2048 * 2048 * 4); // we shouldn't be using this method to downscale huge textures, but it'll work + gGL.getTexUnit(0)->bind(this); + + if (sScratchPBO == 0) + { + glGenBuffers(1, &sScratchPBO); + sScratchPBOSize = 0; + } - glGetTexImage(mTarget, mip, mFormatPrimary, mFormatType, nullptr); + glBindBuffer(GL_PIXEL_PACK_BUFFER, sScratchPBO); - free_tex_image(mTexName); + if (size > sScratchPBOSize) + { + glBufferData(GL_PIXEL_PACK_BUFFER, size, NULL, GL_STREAM_COPY); + sScratchPBOSize = size; + } - glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + glGetTexImage(mTarget, mip, mFormatPrimary, mFormatType, nullptr); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, sScratchPBO); - glTexImage2D(mTarget, 0, mFormatPrimary, desired_width, desired_height, 0, mFormatPrimary, mFormatType, nullptr); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + free_tex_image(mTexName); - alloc_tex_image(desired_width, desired_height, mFormatPrimary); + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - if (mHasMipMaps) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glGenerateMipmap"); - glGenerateMipmap(mTarget); - } + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, sScratchPBO); + glTexImage2D(mTarget, 0, mFormatPrimary, desired_width, desired_height, 0, mFormatPrimary, mFormatType, nullptr); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + alloc_tex_image(desired_width, desired_height, mFormatPrimary); + + if (mHasMipMaps) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glGenerateMipmap"); + glGenerateMipmap(mTarget); + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } mCurrentDiscardLevel = desired_discard; diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 3892e9c014..5073701c30 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -62,6 +62,9 @@ class LLImageGL : public LLRefCount friend class LLTexUnit; public: + // call once per frame + static void updateClass(); + // Get an estimate of how many bytes have been allocated in vram for textures. // Does not include mipmaps. // NOTE: multiplying this number by two gives a good estimate for total @@ -276,7 +279,7 @@ protected: public: static std::unordered_set sImageList; static S32 sCount; - + static U32 sFrameCount; static F32 sLastFrameTime; // Global memory statistics diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index be9f3895e7..e6b4118beb 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -297,7 +297,11 @@ public: ALTERNATE_DIFFUSE_MAP = 1, NORMAL_MAP = 1, SPECULAR_MAP = 2, - NUM_TEXTURE_CHANNELS = 3, + BASECOLOR_MAP = 3, + METALLIC_ROUGHNESS_MAP = 4, + GLTF_NORMAL_MAP = 5, + EMISSIVE_MAP = 6, + NUM_TEXTURE_CHANNELS = 7, }; enum eVolumeTexIndex : U8 diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index efdde77a32..60159a0497 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -426,14 +426,17 @@ void LLRenderTarget::bindTarget() GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3}; - glDrawBuffers(static_cast(mTex.size()), drawbuffers); if (mTex.empty()) { //no color buffer to draw to glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); } - + else + { + glDrawBuffers(static_cast(mTex.size()), drawbuffers); + glReadBuffer(GL_COLOR_ATTACHMENT0); + } check_framebuffer_status(); glViewport(0, 0, mResX, mResY); @@ -519,7 +522,8 @@ void LLRenderTarget::flush() llassert(sCurFBO == mFBO); llassert(sBoundTarget == this); - if (mGenerateMipMaps == LLTexUnit::TMG_AUTO) { + if (mGenerateMipMaps == LLTexUnit::TMG_AUTO) + { LL_PROFILE_GPU_ZONE("rt generate mipmaps"); bindTexture(0, 0, LLTexUnit::TFO_TRILINEAR); glGenerateMipmap(GL_TEXTURE_2D); @@ -540,6 +544,8 @@ void LLRenderTarget::flush() glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); sCurResX = gGLViewport[2]; sCurResY = gGLViewport[3]; + glReadBuffer(GL_BACK); + glDrawBuffer(GL_BACK); } } diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index 340276a752..a1adf93fa1 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -172,6 +172,8 @@ public: // *HACK void swapFBORefs(LLRenderTarget& other); + static LLRenderTarget* sBoundTarget; + protected: U32 mResX; U32 mResY; @@ -186,8 +188,6 @@ protected: U32 mMipLevels; LLTexUnit::eTextureType mUsage; - - static LLRenderTarget* sBoundTarget; }; #endif -- cgit v1.2.3 From 9ddf64c65183960ffed4fe61c5d85e8bacaea030 Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Fri, 5 Jul 2024 18:46:30 +0200 Subject: #1931 BugSplat Crash: SecondLifeViewer!LLRenderTarget::release(387) --- indra/llrender/llrendertarget.cpp | 4 ++++ indra/llrender/llrendertarget.h | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 60159a0497..410efe9a70 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -50,6 +50,7 @@ void check_framebuffer_status() } } +bool LLRenderTarget::sInitFailed = false; bool LLRenderTarget::sUseFBO = false; U32 LLRenderTarget::sCurFBO = 0; @@ -352,6 +353,9 @@ void LLRenderTarget::release() LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; llassert(!isBoundInStack()); + if (sInitFailed) + return; + if (mDepth) { LLImageGL::deleteTextures(1, &mDepth); diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index a1adf93fa1..fc78f059e0 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -61,7 +61,9 @@ class LLRenderTarget { public: - //whether or not to use FBO implementation + // Whether app initialization failed + static bool sInitFailed; + // Whether or not to use FBO implementation static bool sUseFBO; static U32 sBytesAllocated; static U32 sCurFBO; -- cgit v1.2.3 From d0173ac7fc1f999b31aad70c3abfa2c57f872899 Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Sat, 6 Jul 2024 09:23:39 +0200 Subject: #1931 Terminate AppViewer immediately in case of initialization failed --- indra/llrender/llrendertarget.cpp | 4 ---- indra/llrender/llrendertarget.h | 2 -- 2 files changed, 6 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 410efe9a70..60159a0497 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -50,7 +50,6 @@ void check_framebuffer_status() } } -bool LLRenderTarget::sInitFailed = false; bool LLRenderTarget::sUseFBO = false; U32 LLRenderTarget::sCurFBO = 0; @@ -353,9 +352,6 @@ void LLRenderTarget::release() LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; llassert(!isBoundInStack()); - if (sInitFailed) - return; - if (mDepth) { LLImageGL::deleteTextures(1, &mDepth); diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index fc78f059e0..cd3290cf66 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -61,8 +61,6 @@ class LLRenderTarget { public: - // Whether app initialization failed - static bool sInitFailed; // Whether or not to use FBO implementation static bool sUseFBO; static U32 sBytesAllocated; -- cgit v1.2.3 From 9fdca96f8bd2211a99fe88e57b70cbecefa20b6d Mon Sep 17 00:00:00 2001 From: Ansariel Date: Mon, 8 Jul 2024 20:27:14 +0200 Subject: Re-enable compiler warnings C4244 and C4396 except for lltracerecording.h and llunittype.h for now --- indra/llrender/llfontfreetype.cpp | 2 +- indra/llrender/llfontfreetypesvg.cpp | 20 ++++++++++---------- indra/llrender/llfontgl.cpp | 4 ++-- indra/llrender/llfontregistry.cpp | 2 +- indra/llrender/llglslshader.cpp | 16 ++++++++-------- indra/llrender/llimagegl.cpp | 6 +++--- indra/llrender/llpostprocess.cpp | 2 +- indra/llrender/llrender2dutils.cpp | 14 +++++++------- indra/llrender/llrendertarget.cpp | 2 +- indra/llrender/llshadermgr.cpp | 8 ++++---- indra/llrender/lluiimage.cpp | 6 +++--- 11 files changed, 41 insertions(+), 41 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 741ed993b0..6128e03fa7 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -178,7 +178,7 @@ unsigned long ft_read_cb(FT_Stream stream, unsigned long offset, unsigned char * llifstream *file_stream = static_cast(stream->descriptor.pointer); file_stream->seekg(offset, std::ios::beg); file_stream->read((char*)buffer, count); - return file_stream->gcount(); + return (unsigned long)file_stream->gcount(); } void ft_close_cb(FT_Stream stream) { diff --git a/indra/llrender/llfontfreetypesvg.cpp b/indra/llrender/llfontfreetypesvg.cpp index 355e8432aa..71f751329e 100644 --- a/indra/llrender/llfontfreetypesvg.cpp +++ b/indra/llrender/llfontfreetypesvg.cpp @@ -136,18 +136,18 @@ FT_Error LLFontFreeTypeSvgRenderer::OnPresetGlypthSlot(FT_GlyphSlot glyph_slot, float svg_scale = llmin(svg_x_scale, svg_y_scale); datap->Scale = svg_scale; - glyph_slot->bitmap.width = floorf(svg_width) * svg_scale; - glyph_slot->bitmap.rows = floorf(svg_height) * svg_scale; + glyph_slot->bitmap.width = (unsigned int)(floorf(svg_width) * svg_scale); + glyph_slot->bitmap.rows = (unsigned int)(floorf(svg_height) * svg_scale); glyph_slot->bitmap_left = (document->metrics.x_ppem - glyph_slot->bitmap.width) / 2; - glyph_slot->bitmap_top = glyph_slot->face->size->metrics.ascender / 64.f; + glyph_slot->bitmap_top = (FT_Int)(glyph_slot->face->size->metrics.ascender / 64.f); glyph_slot->bitmap.pitch = glyph_slot->bitmap.width * 4; glyph_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA; /* Copied as-is from fcft (MIT license) */ // Compute all the bearings and set them correctly. The outline is scaled already, we just need to use the bounding box. - float horiBearingX = 0.; - float horiBearingY = -glyph_slot->bitmap_top; + float horiBearingX = 0.f; + float horiBearingY = -(float)glyph_slot->bitmap_top; // XXX parentheses correct? float vertBearingX = glyph_slot->metrics.horiBearingX / 64.0f - glyph_slot->metrics.horiAdvance / 64.0f / 2; @@ -156,13 +156,13 @@ FT_Error LLFontFreeTypeSvgRenderer::OnPresetGlypthSlot(FT_GlyphSlot glyph_slot, // Do conversion in two steps to avoid 'bad function cast' warning glyph_slot->metrics.width = glyph_slot->bitmap.width * 64; glyph_slot->metrics.height = glyph_slot->bitmap.rows * 64; - glyph_slot->metrics.horiBearingX = horiBearingX * 64; - glyph_slot->metrics.horiBearingY = horiBearingY * 64; - glyph_slot->metrics.vertBearingX = vertBearingX * 64; - glyph_slot->metrics.vertBearingY = vertBearingY * 64; + glyph_slot->metrics.horiBearingX = (FT_Pos)(horiBearingX * 64); + glyph_slot->metrics.horiBearingY = (FT_Pos)(horiBearingY * 64); + glyph_slot->metrics.vertBearingX = (FT_Pos)(vertBearingX * 64); + glyph_slot->metrics.vertBearingY = (FT_Pos)(vertBearingY * 64); if (glyph_slot->metrics.vertAdvance == 0) { - glyph_slot->metrics.vertAdvance = glyph_slot->bitmap.rows * 1.2f * 64; + glyph_slot->metrics.vertAdvance = (FT_Pos)(glyph_slot->bitmap.rows * 1.2f * 64); } return FT_Err_Ok; diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 59ee8ef84f..04aebdde90 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -112,7 +112,7 @@ S32 LLFontGL::getNumFaces(const std::string& filename) S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRect& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, F32* right_x, bool use_ellipses, bool use_color) const { - LLRectf rect_float(rect.mLeft, rect.mTop, rect.mRight, rect.mBottom); + LLRectf rect_float((F32)rect.mLeft, (F32)rect.mTop, (F32)rect.mRight, (F32)rect.mBottom); return render(wstr, begin_offset, rect_float, color, halign, valign, style, shadow, max_chars, right_x, use_ellipses, use_color); } @@ -138,7 +138,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRectf& rec y = rect.mBottom; break; } - return render(wstr, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, rect.getWidth(), right_x, use_ellipses, use_color); + return render(wstr, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, (S32)rect.getWidth(), right_x, use_ellipses, use_color); } diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 62f4f35e3d..c48a389f6a 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -500,7 +500,7 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) // *HACK: Fallback fonts don't render, so we can use that to suppress // creation of OpenGL textures for test apps. JC bool is_fallback = !is_first_found || !mCreateGLTextures; - F32 extra_scale = (is_fallback)?fallback_scale:1.0; + F32 extra_scale = (is_fallback) ? fallback_scale : 1.0f; F32 point_size_scale = extra_scale * point_size; bool is_font_loaded = false; for(string_vec_t::iterator font_search_path_it = font_search_paths.begin(); diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 25e4a88f28..e76a30a954 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -190,7 +190,7 @@ void LLGLSLShader::dumpStats() tris_sec /= seconds; F32 pct_samples = (F32)((F64)mSamplesDrawn / (F64)sTotalSamplesDrawn) * 100.f; - F32 samples_sec = (F32)mSamplesDrawn / 1000000000.0; + F32 samples_sec = (F32)(mSamplesDrawn / 1000000000.0); samples_sec /= seconds; F32 pct_binds = (F32)mBinds / (F32)sTotalBinds * 100.f; @@ -1265,7 +1265,7 @@ void LLGLSLShader::uniform1i(U32 index, GLint x) if (iter == mValue.end() || iter->second.mV[0] != x) { glUniform1i(mUniform[index], x); - mValue[mUniform[index]] = LLVector4(x, 0.f, 0.f, 0.f); + mValue[mUniform[index]] = LLVector4((F32)x, 0.f, 0.f, 0.f); } } } @@ -1405,7 +1405,7 @@ void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v) if (mUniform[index] >= 0) { const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(v[0], 0.f, 0.f, 0.f); + LLVector4 vec((F32)v[0], 0.f, 0.f, 0.f); if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) { glUniform1iv(mUniform[index], count, v); @@ -1432,7 +1432,7 @@ void LLGLSLShader::uniform4iv(U32 index, U32 count, const GLint* v) if (mUniform[index] >= 0) { const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(v[0], v[1], v[2], v[3]); + LLVector4 vec((F32)v[0], (F32)v[1], (F32)v[2], (F32)v[3]); if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) { glUniform1iv(mUniform[index], count, v); @@ -1702,7 +1702,7 @@ void LLGLSLShader::uniform1i(const LLStaticHashedString& uniform, GLint v) if (location >= 0) { const auto& iter = mValue.find(location); - LLVector4 vec(v, 0.f, 0.f, 0.f); + LLVector4 vec((F32)v, 0.f, 0.f, 0.f); if (iter == mValue.end() || shouldChange(iter->second, vec)) { glUniform1i(location, v); @@ -1718,7 +1718,7 @@ void LLGLSLShader::uniform1iv(const LLStaticHashedString& uniform, U32 count, co if (location >= 0) { - LLVector4 vec(v[0], 0, 0, 0); + LLVector4 vec((F32)v[0], 0.f, 0.f, 0.f); const auto& iter = mValue.find(location); if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) { @@ -1736,7 +1736,7 @@ void LLGLSLShader::uniform4iv(const LLStaticHashedString& uniform, U32 count, co if (location >= 0) { - LLVector4 vec(v[0], v[1], v[2], v[3]); + LLVector4 vec((F32)v[0], (F32)v[1], (F32)v[2], (F32)v[3]); const auto& iter = mValue.find(location); if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) { @@ -1755,7 +1755,7 @@ void LLGLSLShader::uniform2i(const LLStaticHashedString& uniform, GLint i, GLint if (location >= 0) { const auto& iter = mValue.find(location); - LLVector4 vec(i, j, 0.f, 0.f); + LLVector4 vec((F32)i, (F32)j, 0.f, 0.f); if (iter == mValue.end() || shouldChange(iter->second, vec)) { glUniform2i(location, i, j); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 34200ef5cb..058afa0cf2 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -738,7 +738,7 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 } if (is_compressed) { - S32 tex_size = dataFormatBytes(mFormatPrimary, w, h); + GLsizei tex_size = (GLsizei)dataFormatBytes(mFormatPrimary, w, h); glCompressedTexImage2D(mTarget, gl_level, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in); stop_glerror(); } @@ -941,7 +941,7 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 S32 h = getHeight(); if (is_compressed) { - S32 tex_size = dataFormatBytes(mFormatPrimary, w, h); + GLsizei tex_size = (GLsizei)dataFormatBytes(mFormatPrimary, w, h); glCompressedTexImage2D(mTarget, 0, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in); stop_glerror(); } @@ -2418,7 +2418,7 @@ bool LLImageGL::scaleDown(S32 desired_discard) if (size > sScratchPBOSize) { glBufferData(GL_PIXEL_PACK_BUFFER, size, NULL, GL_STREAM_COPY); - sScratchPBOSize = size; + sScratchPBOSize = (U32)size; } glGetTexImage(mTarget, mip, mFormatPrimary, mFormatType, nullptr); diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp index 8ebd09f20d..eef7193c92 100644 --- a/indra/llrender/llpostprocess.cpp +++ b/indra/llrender/llpostprocess.cpp @@ -343,7 +343,7 @@ void LLPostProcess::viewOrthogonal(unsigned int width, unsigned int height) gGL.matrixMode(LLRender::MM_PROJECTION); gGL.pushMatrix(); gGL.loadIdentity(); - gGL.ortho( 0.f, (GLdouble) width , (GLdouble) height , 0.f, -1.f, 1.f ); + gGL.ortho( 0.f, (GLfloat) width , (GLfloat) height , 0.f, -1.f, 1.f ); gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.pushMatrix(); gGL.loadIdentity(); diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index ef02fbd071..176c7a5d2c 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -364,7 +364,7 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex { // add in offset of current image to current UI translation const LLVector3 ui_scale = gGL.getUIScale(); - const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale); + const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3((F32)x, (F32)y, 0.f)).scaledVec(ui_scale); F32 uv_width = uv_outer_rect.getWidth(); F32 uv_height = uv_outer_rect.getHeight(); @@ -375,8 +375,8 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex uv_outer_rect.mLeft + (center_rect.mRight * uv_width), uv_outer_rect.mBottom + (center_rect.mBottom * uv_height)); - F32 image_width = image->getWidth(0); - F32 image_height = image->getHeight(0); + F32 image_width = (F32)image->getWidth(0); + F32 image_height = (F32)image->getHeight(0); S32 image_natural_width = ll_round(image_width * uv_width); S32 image_natural_height = ll_round(image_height * uv_height); @@ -413,10 +413,10 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex draw_center_rect.setCenterAndSize(uv_center_rect.getCenterX() * width, uv_center_rect.getCenterY() * height, scaled_width, scaled_height); } - draw_center_rect.mLeft = ll_round(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * ui_scale.mV[VX]); - draw_center_rect.mTop = ll_round(ui_translation.mV[VY] + (F32)draw_center_rect.mTop * ui_scale.mV[VY]); - draw_center_rect.mRight = ll_round(ui_translation.mV[VX] + (F32)draw_center_rect.mRight * ui_scale.mV[VX]); - draw_center_rect.mBottom = ll_round(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * ui_scale.mV[VY]); + draw_center_rect.mLeft = (F32)ll_round(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * ui_scale.mV[VX]); + draw_center_rect.mTop = (F32)ll_round(ui_translation.mV[VY] + (F32)draw_center_rect.mTop * ui_scale.mV[VY]); + draw_center_rect.mRight = (F32)ll_round(ui_translation.mV[VX] + (F32)draw_center_rect.mRight * ui_scale.mV[VX]); + draw_center_rect.mBottom = (F32)ll_round(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * ui_scale.mV[VY]); LLRectf draw_outer_rect(ui_translation.mV[VX], ui_translation.mV[VY] + height * ui_scale.mV[VY], diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 410efe9a70..015819c1bd 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -124,7 +124,7 @@ bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, LLT if (mGenerateMipMaps != LLTexUnit::TMG_NONE) { // Calculate the number of mip levels based upon resolution that we should have. - mMipLevels = 1 + floor(log10((float)llmax(mResX, mResY))/log10(2.0)); + mMipLevels = 1 + (U32)floor(log10((float)llmax(mResX, mResY)) / log10(2.0)); } if (depth) diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index a8e9f20b40..8bc00c0cf6 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1003,7 +1003,7 @@ void LLShaderMgr::initShaderCache(bool enabled, const LLUUID& old_cache_version, ProgramBinaryData binary_info = ProgramBinaryData(); binary_info.mBinaryFormat = data_pair.second["binary_format"].asInteger(); binary_info.mBinaryLength = data_pair.second["binary_size"].asInteger(); - binary_info.mLastUsedTime = data_pair.second["last_used"].asReal(); + binary_info.mLastUsedTime = (F32)data_pair.second["last_used"].asReal(); mShaderBinaryCache.insert_or_assign(LLUUID(data_pair.first), binary_info); } } @@ -1034,7 +1034,7 @@ void LLShaderMgr::persistShaderCacheMetadata() LLSD out = LLSD::emptyMap(); static const F32 LRU_TIME = (60.f * 60.f) * 24.f * 7.f; // 14 days - const F32 current_time = LLTimer::getTotalSeconds(); + const F32 current_time = (F32)LLTimer::getTotalSeconds(); for (auto it = mShaderBinaryCache.begin(); it != mShaderBinaryCache.end();) { const ProgramBinaryData& shader_metadata = it->second; @@ -1093,7 +1093,7 @@ bool LLShaderMgr::loadCachedProgramBinary(LLGLSLShader* shader) glGetProgramiv(shader->mProgramObject, GL_LINK_STATUS, &success); if (error == GL_NO_ERROR && success == GL_TRUE) { - binary_iter->second.mLastUsedTime = LLTimer::getTotalSeconds(); + binary_iter->second.mLastUsedTime = (F32)LLTimer::getTotalSeconds(); LL_INFOS() << "Loaded cached binary for shader: " << shader->mName << LL_ENDL; return true; } @@ -1131,7 +1131,7 @@ bool LLShaderMgr::saveCachedProgramBinary(LLGLSLShader* shader) fwrite(program_binary.data(), sizeof(U8), program_binary.size(), outfile); outfile.close(); - binary_info.mLastUsedTime = LLTimer::getTotalSeconds(); + binary_info.mLastUsedTime = (F32)LLTimer::getTotalSeconds(); mShaderBinaryCache.insert_or_assign(shader->mShaderHash, binary_info); return true; diff --git a/indra/llrender/lluiimage.cpp b/indra/llrender/lluiimage.cpp index bcf665ca18..d31a91e2af 100644 --- a/indra/llrender/lluiimage.cpp +++ b/indra/llrender/lluiimage.cpp @@ -83,7 +83,7 @@ void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, c LLRender2D::getInstance()->pushMatrix(); { - LLVector3 rect_origin = origin_agent + (rect.mLeft * x_axis) + (rect.mBottom * y_axis); + LLVector3 rect_origin = origin_agent + ((F32)rect.mLeft * x_axis) + ((F32)rect.mBottom * y_axis); LLRender2D::getInstance()->translate(rect_origin.mV[VX], rect_origin.mV[VY], rect_origin.mV[VZ]); @@ -100,8 +100,8 @@ void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, c (rect.getHeight() - (border_height * border_scale * 0.5f)) / (F32)rect.getHeight(), (rect.getWidth() - (border_width * border_scale * 0.5f)) / (F32)rect.getWidth(), (border_height * border_scale * 0.5f) / (F32)rect.getHeight()), - rect.getWidth() * x_axis, - rect.getHeight() * y_axis); + (F32)rect.getWidth() * x_axis, + (F32)rect.getHeight() * y_axis); } LLRender2D::getInstance()->popMatrix(); } -- cgit v1.2.3 From 2a7030992faa12c362d3eb9365080efd8265e15f Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Tue, 9 Jul 2024 17:53:43 -0400 Subject: Update tracy profiler to 0.10 (#1946) --- indra/llrender/llfontgl.cpp | 8 ++++---- indra/llrender/llrender.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 04aebdde90..b9a4235a4e 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -560,7 +560,7 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars void LLFontGL::generateASCIIglyphs() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_UI + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; for (U32 i = 32; (i < 127); i++) { mFontFreetype->getGlyphInfo(i, EFontGlyphType::Grayscale); @@ -570,7 +570,7 @@ void LLFontGL::generateASCIIglyphs() // Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars, EWordWrapStyle end_on_word_boundary) const { - LL_PROFILE_ZONE_SCOPED_CATEGORY_UI + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; if (!wchars || !wchars[0] || max_chars == 0) { return 0; @@ -881,7 +881,7 @@ void LLFontGL::dumpFontTextures() // static bool LLFontGL::loadDefaultFonts() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_UI + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; bool succ = true; succ &= (NULL != getFontSansSerifSmall()); succ &= (NULL != getFontSansSerif()); @@ -894,7 +894,7 @@ bool LLFontGL::loadDefaultFonts() void LLFontGL::loadCommonFonts() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_UI + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; getFont(LLFontDescriptor("SansSerif", "Small", BOLD)); getFont(LLFontDescriptor("SansSerif", "Large", BOLD)); getFont(LLFontDescriptor("SansSerif", "Huge", BOLD)); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index a0209fab43..1301d325a0 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1514,7 +1514,7 @@ LLLightState* LLRender::getLight(U32 index) void LLRender::setAmbientLightColor(const LLColor4& color) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE + LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; if (color != mAmbientLightColor) { ++mLightHash; -- cgit v1.2.3 From e101d1aa28a51570e6d76dc12df810b1daa71e7e Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Tue, 9 Jul 2024 20:51:02 -0400 Subject: Fix excessive clearing of shader cache when toggling mirrors (#1950) --- indra/llrender/llshadermgr.cpp | 6 ------ indra/llrender/llshadermgr.h | 1 - 2 files changed, 7 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 8bc00c0cf6..bc542d325e 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -44,7 +44,6 @@ using std::make_pair; using std::string; LLShaderMgr * LLShaderMgr::sInstance = NULL; -bool LLShaderMgr::sMirrorsEnabled = false; LLShaderMgr::LLShaderMgr() { @@ -600,11 +599,6 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n"); } - if (sMirrorsEnabled) - { - extra_code_text[extra_code_count++] = strdup("#define HERO_PROBES 1\n"); - } - // Use alpha float to store bit flags // See: C++: addDeferredAttachment(), shader: frag_data[2] extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_SKIP_ATMOS 0.0 \n"); // atmo kill diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index fe6137c448..921ef20997 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -378,7 +378,6 @@ public: bool mShaderCacheInitialized = false; bool mShaderCacheEnabled = false; std::string mShaderCacheDir; - static bool sMirrorsEnabled; protected: -- cgit v1.2.3 From 604cb4cb4dd71c0f90633e50d5b0108e3901c4ad Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Fri, 26 Jul 2024 06:19:34 -0400 Subject: Reduce utf8 to wstring conversion and llwstring temporaries during text draw (#2115) --- indra/llrender/llfontgl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index b9a4235a4e..b6cdb81b33 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -406,7 +406,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons // recursively render ellipses at end of string // we've already reserved enough room gGL.pushUIMatrix(); - renderUTF8(std::string("..."), + static LLWString elipses_wstr(utf8string_to_wstring(std::string("..."))); + render(elipses_wstr, 0, (cur_x - origin.mV[VX]) / sScaleX, (F32)y, color, -- cgit v1.2.3 From 75455d101c9535d0d45aa0f505f888f4ba3de64d Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Tue, 6 Aug 2024 09:21:19 -0400 Subject: Convert LLUI and LLRender2D to LLSimpleton to reduce overhead during ui draw (#2202) --- indra/llrender/llrender2dutils.cpp | 2 +- indra/llrender/llrender2dutils.h | 7 ++++--- indra/llrender/lluiimage.cpp | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index 176c7a5d2c..428370057e 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -726,7 +726,7 @@ void gl_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& c } gGL.end(); - LLRender2D::getInstance()->setLineWidth(1.f); + LLRender2D::setLineWidth(1.f); } void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, bool filled, F32 start_angle, F32 end_angle) diff --git a/indra/llrender/llrender2dutils.h b/indra/llrender/llrender2dutils.h index 0d3efc38d6..096e7584f1 100644 --- a/indra/llrender/llrender2dutils.h +++ b/indra/llrender/llrender2dutils.h @@ -122,12 +122,13 @@ inline void gl_rect_2d_offset_local( const LLRect& rect, S32 pixel_offset, bool class LLImageProviderInterface; -class LLRender2D : public LLParamSingleton +class LLRender2D : public LLSimpleton { - LLSINGLETON(LLRender2D, LLImageProviderInterface* image_provider); LOG_CLASS(LLRender2D); - ~LLRender2D(); public: + LLRender2D(LLImageProviderInterface* image_provider); + ~LLRender2D(); + static void pushMatrix(); static void popMatrix(); static void loadIdentity(); diff --git a/indra/llrender/lluiimage.cpp b/indra/llrender/lluiimage.cpp index d31a91e2af..dc18bf16bf 100644 --- a/indra/llrender/lluiimage.cpp +++ b/indra/llrender/lluiimage.cpp @@ -81,10 +81,10 @@ void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, c } } - LLRender2D::getInstance()->pushMatrix(); + LLRender2D::pushMatrix(); { LLVector3 rect_origin = origin_agent + ((F32)rect.mLeft * x_axis) + ((F32)rect.mBottom * y_axis); - LLRender2D::getInstance()->translate(rect_origin.mV[VX], + LLRender2D::translate(rect_origin.mV[VX], rect_origin.mV[VY], rect_origin.mV[VZ]); gGL.getTexUnit(0)->bind(getImage()); @@ -103,7 +103,7 @@ void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, c (F32)rect.getWidth() * x_axis, (F32)rect.getHeight() * y_axis); - } LLRender2D::getInstance()->popMatrix(); + } LLRender2D::popMatrix(); } //#include "lluiimage.inl" -- cgit v1.2.3 From 6aa9110b2ae346da1a396500cae1b41e8e2d5b75 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Thu, 11 Jul 2024 15:54:24 -0700 Subject: secondlife/viewer#1883: Local-only PBR terrain paintmap with developer tools --- indra/llrender/llshadermgr.cpp | 3 +++ indra/llrender/llshadermgr.h | 3 +++ 2 files changed, 6 insertions(+) (limited to 'indra/llrender') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index bc542d325e..512ef340f9 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1409,6 +1409,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("detail_3"); mReservedUniforms.push_back("alpha_ramp"); + mReservedUniforms.push_back("paint_map"); mReservedUniforms.push_back("detail_0_base_color"); mReservedUniforms.push_back("detail_1_base_color"); @@ -1433,6 +1434,8 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("emissiveColors"); mReservedUniforms.push_back("minimum_alphas"); + mReservedUniforms.push_back("region_scale"); + mReservedUniforms.push_back("origin"); mReservedUniforms.push_back("display_gamma"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 921ef20997..2b76ef664b 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -267,6 +267,7 @@ public: TERRAIN_DETAIL3, // "detail_3" TERRAIN_ALPHARAMP, // "alpha_ramp" + TERRAIN_PAINTMAP, // "paint_map" TERRAIN_DETAIL0_BASE_COLOR, // "detail_0_base_color" (GLTF) TERRAIN_DETAIL1_BASE_COLOR, // "detail_1_base_color" (GLTF) @@ -291,6 +292,8 @@ public: TERRAIN_EMISSIVE_COLORS, // "emissiveColors" (GLTF) TERRAIN_MINIMUM_ALPHAS, // "minimum_alphas" (GLTF) + REGION_SCALE, // "region_scale" (GLTF) + SHINY_ORIGIN, // "origin" DISPLAY_GAMMA, // "display_gamma" -- cgit v1.2.3 From 17f7b439d617bfdf4c865f1478ade662e86b61d2 Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Wed, 7 Aug 2024 20:56:10 +0200 Subject: #1922 Make PBR scale and offset crosshair work like Texture crosshair do --- indra/llrender/llrender.h | 19 +++++++++++-------- indra/llrender/llvertexbuffer.cpp | 12 ++++++++++++ indra/llrender/llvertexbuffer.h | 9 +++++---- 3 files changed, 28 insertions(+), 12 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index e6b4118beb..010ab122b6 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -293,15 +293,18 @@ public: enum eTexIndex : U8 { - DIFFUSE_MAP = 0, - ALTERNATE_DIFFUSE_MAP = 1, - NORMAL_MAP = 1, - SPECULAR_MAP = 2, - BASECOLOR_MAP = 3, + // Channels for material textures + DIFFUSE_MAP = 0, + ALTERNATE_DIFFUSE_MAP = 1, + NORMAL_MAP = 1, + SPECULAR_MAP = 2, + // Channels for PBR textures + BASECOLOR_MAP = 3, METALLIC_ROUGHNESS_MAP = 4, - GLTF_NORMAL_MAP = 5, - EMISSIVE_MAP = 6, - NUM_TEXTURE_CHANNELS = 7, + GLTF_NORMAL_MAP = 5, + EMISSIVE_MAP = 6, + // Total number of channels + NUM_TEXTURE_CHANNELS = 7, }; enum eVolumeTexIndex : U8 diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 2eb7c21f77..02afcf12c6 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -794,6 +794,18 @@ void LLVertexBuffer::setLabel(const char* label) { } #endif +void LLVertexBuffer::clone(LLVertexBuffer& target) const +{ + target.mTypeMask = mTypeMask; + target.mIndicesType = mIndicesType; + target.mIndicesStride = mIndicesStride; + if (target.getNumVerts() != getNumVerts() || + target.getNumIndices() != getNumIndices()) + { + target.allocateBuffer(getNumVerts(), getNumIndices()); + } +} + void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const { llassert(validateRange(start, end, count, indices_offset)); diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 49500e28ce..4ada0c335b 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -163,13 +163,13 @@ public: // set for rendering // assumes (and will assert on) the following: - // - this buffer has no pending unampBuffer call + // - this buffer has no pending unmapBuffer call // - a shader is currently bound // - This buffer has sufficient attributes within it to satisfy the needs of the currently bound shader void setBuffer(); // Only call each getVertexPointer, etc, once before calling unmapBuffer() - // call unmapBuffer() after calls to getXXXStrider() before any cals to setBuffer() + // call unmapBuffer() after calls to getXXXStrider() before any calls to setBuffer() // example: // vb->getVertexBuffer(verts); // vb->getNormalStrider(norms); @@ -218,12 +218,12 @@ public: U32 getNumIndices() const { return mNumIndices; } U32 getTypeMask() const { return mTypeMask; } - bool hasDataType(AttributeType type) const { return ((1 << type) & getTypeMask()); } + bool hasDataType(AttributeType type) const { return ((1 << type) & getTypeMask()); } U32 getSize() const { return mSize; } U32 getIndicesSize() const { return mIndicesSize; } U8* getMappedData() const { return mMappedData; } U8* getMappedIndices() const { return mMappedIndexData; } - U32 getOffset(AttributeType type) const { return mOffsets[type]; } + U32 getOffset(AttributeType type) const { return mOffsets[type]; } // these functions assume (and assert on) the current VBO being bound // Detailed error checking can be enabled by setting gDebugGL to true @@ -242,6 +242,7 @@ public: void setLabel(const char* label); #endif + void clone(LLVertexBuffer& target) const; protected: U32 mGLBuffer = 0; // GL VBO handle -- cgit v1.2.3 From ed6732eda8c80d17e05bbc6563b6ce08ef6b8c72 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 20 Aug 2024 06:59:07 -0500 Subject: #2315 Ensure textures are deleted when they are no longer referenced. (#2343) * #2315 WIP -- Clean up deletion rules in texture list. Incidental decruft. * Touch up assertions. * Move mLastReferencedTimer to LLViewerMediaTexture since it's no longer used by LLViewerTexture --- indra/llrender/llgltexture.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h index a7de20dc5c..122d2a7f9c 100644 --- a/indra/llrender/llgltexture.h +++ b/indra/llrender/llgltexture.h @@ -82,8 +82,6 @@ public: typedef enum { DELETED = 0, //removed from memory - DELETION_CANDIDATE, //ready to be removed from memory - INACTIVE, //not be used for the last certain period (i.e., 30 seconds). ACTIVE, //just being used, can become inactive if not being used for a certain time (10 seconds). NO_DELETE = 99 //stay in memory, can not be removed. } LLGLTextureState; -- cgit v1.2.3 From db84bf9567c27e266ccc6b1b6aed089c6022fe91 Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Wed, 21 Aug 2024 10:47:31 -0400 Subject: Improve accuracy of texture memory tracking (#2371) * Fix alloc_tex_image to account for more missing texture memory Change alloc_tex_image calls to pass internal format to properly account for used image type * Fix scaleDown passing primary format in place of internal format to glTexImage2D * Make texture debug view and texture bias calculation consistent and remove double accounting for render target textures --- indra/llrender/llcubemaparray.cpp | 14 ++++++-------- indra/llrender/llimagegl.cpp | 19 ++++++++++++------- indra/llrender/llimagegl.h | 2 +- 3 files changed, 19 insertions(+), 16 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp index be69b997da..4f5e13765a 100644 --- a/indra/llrender/llcubemaparray.cpp +++ b/indra/llrender/llcubemaparray.cpp @@ -125,27 +125,25 @@ void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, bool us mImage->setHasMipMaps(use_mips); bind(0); + free_cur_tex_image(); U32 format = components == 4 ? GL_RGBA16F : GL_RGB16F; - U32 mip = 0; - - free_cur_tex_image(); - - while (resolution >= 1) + U32 mip_resolution = resolution; + while (mip_resolution >= 1) { - glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, format, resolution, resolution, count * 6, 0, + glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, format, mip_resolution, mip_resolution, count * 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); if (!use_mips) { break; } - resolution /= 2; + mip_resolution /= 2; ++mip; } - alloc_tex_image(resolution * 6, resolution, format); + alloc_tex_image(resolution, resolution, format, count * 6); mImage->setAddressMode(LLTexUnit::TAM_CLAMP); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 058afa0cf2..0746e21079 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -67,11 +67,12 @@ static U64 sTextureBytes = 0; // track a texture alloc on the currently bound texture. // asserts that no currently tracked alloc exists -void LLImageGLMemory::alloc_tex_image(U32 width, U32 height, U32 pixformat) +void LLImageGLMemory::alloc_tex_image(U32 width, U32 height, U32 intformat, U32 count) { U32 texUnit = gGL.getCurrentTexUnitIndex(); U32 texName = gGL.getTexUnit(texUnit)->getCurrTexture(); - U64 size = LLImageGL::dataFormatBytes(pixformat, width, height); + U64 size = LLImageGL::dataFormatBytes(intformat, width, height); + size *= count; llassert(size >= 0); @@ -291,9 +292,13 @@ S32 LLImageGL::dataFormatBits(S32 dataformat) case GL_SRGB: return 24; case GL_RGB8: return 24; case GL_RGBA: return 32; + case GL_RGBA8: return 32; case GL_SRGB_ALPHA: return 32; case GL_BGRA: return 32; // Used for QuickTime media textures on the Mac case GL_DEPTH_COMPONENT: return 24; + case GL_DEPTH_COMPONENT24: return 24; + case GL_R16F: return 16; + case GL_RG16F: return 32; case GL_RGB16F: return 48; case GL_RGBA16F: return 64; default: @@ -1384,7 +1389,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt sub_image_lines(target, miplevel, 0, 0, width, height, pixformat, pixtype, src, width); } } - alloc_tex_image(width, height, pixformat); + alloc_tex_image(width, height, intformat, 1); } stop_glerror(); @@ -2370,11 +2375,11 @@ bool LLImageGL::scaleDown(S32 desired_discard) gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, temp_texname, true); { LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glTexImage2D"); - glTexImage2D(mTarget, 0, mFormatPrimary, desired_width, desired_height, 0, mFormatPrimary, mFormatType, NULL); + glTexImage2D(mTarget, 0, mFormatInternal, desired_width, desired_height, 0, mFormatPrimary, mFormatType, NULL); } // account for new texture getting created - alloc_tex_image(desired_width, desired_height, mFormatPrimary); + alloc_tex_image(desired_width, desired_height, mFormatInternal, 1); // Use render-to-texture to scale down the texture { @@ -2428,10 +2433,10 @@ bool LLImageGL::scaleDown(S32 desired_discard) glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, sScratchPBO); - glTexImage2D(mTarget, 0, mFormatPrimary, desired_width, desired_height, 0, mFormatPrimary, mFormatType, nullptr); + glTexImage2D(mTarget, 0, mFormatInternal, desired_width, desired_height, 0, mFormatPrimary, mFormatType, nullptr); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - alloc_tex_image(desired_width, desired_height, mFormatPrimary); + alloc_tex_image(desired_width, desired_height, mFormatInternal, 1); if (mHasMipMaps) { diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 5073701c30..9a8d935b89 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -50,7 +50,7 @@ class LLWindow; namespace LLImageGLMemory { - void alloc_tex_image(U32 width, U32 height, U32 pixformat); + void alloc_tex_image(U32 width, U32 height, U32 intformat, U32 count); void free_tex_image(U32 texName); void free_tex_images(U32 count, const U32* texNames); void free_cur_tex_image(); -- cgit v1.2.3 From 0e59ed204fdf84c5323837e5c91cfa7da0a9e89b Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 21 Aug 2024 14:36:18 -0500 Subject: Fix crash on Intel GPUs (or anywhere OpenGL compatibility profile is used). (#2387) --- indra/llrender/llimagegl.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra/llrender') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 0746e21079..be30807e7f 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -284,10 +284,13 @@ S32 LLImageGL::dataFormatBits(S32 dataformat) case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return 8; case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 8; case GL_LUMINANCE: return 8; + case GL_LUMINANCE8: return 8; case GL_ALPHA: return 8; + case GL_ALPHA8: return 8; case GL_RED: return 8; case GL_COLOR_INDEX: return 8; case GL_LUMINANCE_ALPHA: return 16; + case GL_LUMINANCE8_ALPHA8: return 16; case GL_RGB: return 24; case GL_SRGB: return 24; case GL_RGB8: return 24; -- cgit v1.2.3 From 28331b2385a8de2a0fde67329127c1694e3f219f Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Thu, 22 Aug 2024 11:25:25 -0400 Subject: Do deprecated texture swizzle on GPU using GL texture swizzling functions (#2389) * Use GL texture swizzling instead of scratch buffer for deprecated formats when GL 3.3 is available Fix crash when GL texture compression is enabled * Fix UI font atlas being eligible for texture compression --- indra/llrender/llfontbitmapcache.cpp | 2 +- indra/llrender/llimagegl.cpp | 216 +++++++++++++++++++++-------------- indra/llrender/llimagegl.h | 8 +- 3 files changed, 135 insertions(+), 91 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llfontbitmapcache.cpp b/indra/llrender/llfontbitmapcache.cpp index 46c2e89797..ee9cfd0719 100644 --- a/indra/llrender/llfontbitmapcache.cpp +++ b/indra/llrender/llfontbitmapcache.cpp @@ -117,7 +117,7 @@ bool LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyp } // Make corresponding GL image. - mImageGLVec[bitmap_idx].push_back(new LLImageGL(image_raw, false)); + mImageGLVec[bitmap_idx].push_back(new LLImageGL(image_raw, false, false)); LLImageGL* image_gl = getImageGL(bitmap_type, bitmap_num); // Start at beginning of the new image. diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index be30807e7f..d5f7949051 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -277,6 +277,15 @@ S32 LLImageGL::dataFormatBits(S32 dataformat) { switch (dataformat) { + case GL_COMPRESSED_RED: return 8; + case GL_COMPRESSED_RG: return 16; + case GL_COMPRESSED_RGB: return 24; + case GL_COMPRESSED_SRGB: return 32; + case GL_COMPRESSED_RGBA: return 32; + case GL_COMPRESSED_SRGB_ALPHA: return 32; + case GL_COMPRESSED_LUMINANCE: return 8; + case GL_COMPRESSED_LUMINANCE_ALPHA: return 16; + case GL_COMPRESSED_ALPHA: return 8; case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return 4; case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 4; case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return 8; @@ -288,9 +297,12 @@ S32 LLImageGL::dataFormatBits(S32 dataformat) case GL_ALPHA: return 8; case GL_ALPHA8: return 8; case GL_RED: return 8; + case GL_R8: return 8; case GL_COLOR_INDEX: return 8; case GL_LUMINANCE_ALPHA: return 16; case GL_LUMINANCE8_ALPHA8: return 16; + case GL_RG: return 16; + case GL_RG8: return 16; case GL_RGB: return 24; case GL_SRGB: return 24; case GL_RGB8: return 24; @@ -348,6 +360,7 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat) case GL_RED: return 1; case GL_COLOR_INDEX: return 1; case GL_LUMINANCE_ALPHA: return 2; + case GL_RG: return 2; case GL_RGB: return 3; case GL_SRGB: return 3; case GL_RGBA: return 4; @@ -415,29 +428,29 @@ bool LLImageGL::create(LLPointer& dest, const LLImageRaw* imageraw, b //---------------------------------------------------------------------------- -LLImageGL::LLImageGL(bool usemipmaps) +LLImageGL::LLImageGL(bool usemipmaps/* = true*/, bool allow_compression/* = true*/) : mSaveData(0), mExternalTexture(false) { - init(usemipmaps); + init(usemipmaps, allow_compression); setSize(0, 0, 0); sImageList.insert(this); sCount++; } -LLImageGL::LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps) +LLImageGL::LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps/* = true*/, bool allow_compression/* = true*/) : mSaveData(0), mExternalTexture(false) { llassert( components <= 4 ); - init(usemipmaps); + init(usemipmaps, allow_compression); setSize(width, height, components); sImageList.insert(this); sCount++; } -LLImageGL::LLImageGL(const LLImageRaw* imageraw, bool usemipmaps) +LLImageGL::LLImageGL(const LLImageRaw* imageraw, bool usemipmaps/* = true*/, bool allow_compression/* = true*/) : mSaveData(0), mExternalTexture(false) { - init(usemipmaps); + init(usemipmaps, allow_compression); setSize(0, 0, 0); sImageList.insert(this); sCount++; @@ -454,7 +467,7 @@ LLImageGL::LLImageGL( LLGLenum formatType, LLTexUnit::eTextureAddressMode addressMode) { - init(false); + init(false, true); mTexName = texName; mTarget = target; mComponents = components; @@ -476,7 +489,7 @@ LLImageGL::~LLImageGL() } } -void LLImageGL::init(bool usemipmaps) +void LLImageGL::init(bool usemipmaps, bool allow_compression) { #if LL_IMAGEGL_THREAD_CHECK mActiveThread = LLThread::currentID(); @@ -506,7 +519,7 @@ void LLImageGL::init(bool usemipmaps) mHeight = 0; mCurrentDiscardLevel = -1; - mAllowCompression = true; + mAllowCompression = allow_compression; mTarget = GL_TEXTURE_2D; mBindTarget = LLTexUnit::TT_TEXTURE; @@ -1234,90 +1247,122 @@ void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures) void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void* pixels, bool allow_compression) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - bool use_scratch = false; - U32* scratch = NULL; + std::unique_ptr scratch; if (LLRender::sGLCoreProfile) { - if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE) - { //GL_ALPHA is deprecated, convert to RGBA - if (pixels != nullptr) - { - use_scratch = true; - scratch = new(std::nothrow) U32[width * height]; - if (!scratch) - { - LLError::LLUserWarningMsg::showOutOfMemory(); - LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32)) - << " bytes for a manual image W" << width << " H" << height << LL_ENDL; - } + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + if (gGLManager.mGLVersion >= 3.29f) + { + if (pixformat == GL_ALPHA) + { //GL_ALPHA is deprecated, convert to RGBA + const GLint mask[] = { GL_ZERO, GL_ZERO, GL_ZERO, GL_RED }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, mask); + pixformat = GL_RED; + intformat = GL_R8; + } - U32 pixel_count = (U32)(width * height); - for (U32 i = 0; i < pixel_count; i++) - { - U8* pix = (U8*)&scratch[i]; - pix[0] = pix[1] = pix[2] = 0; - pix[3] = ((U8*)pixels)[i]; - } + if (pixformat == GL_LUMINANCE) + { //GL_LUMINANCE is deprecated, convert to GL_RGBA + const GLint mask[] = { GL_RED, GL_RED, GL_RED, GL_ONE }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, mask); + pixformat = GL_RED; + intformat = GL_R8; } - pixformat = GL_RGBA; - intformat = GL_RGBA8; + if (pixformat == GL_LUMINANCE_ALPHA) + { //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA + const GLint mask[] = { GL_RED, GL_RED, GL_RED, GL_GREEN }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, mask); + pixformat = GL_RG; + intformat = GL_RG8; + } } - - if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE) - { //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA - if (pixels != nullptr) - { - use_scratch = true; - scratch = new(std::nothrow) U32[width * height]; - if (!scratch) + else + { + if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE) + { //GL_ALPHA is deprecated, convert to RGBA + if (pixels != nullptr) { - LLError::LLUserWarningMsg::showOutOfMemory(); - LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32)) - << " bytes for a manual image W" << width << " H" << height << LL_ENDL; - } + scratch.reset(new(std::nothrow) U32[width * height]); + if (!scratch) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32)) + << " bytes for a manual image W" << width << " H" << height << LL_ENDL; + } - U32 pixel_count = (U32)(width * height); - for (U32 i = 0; i < pixel_count; i++) - { - U8 lum = ((U8*)pixels)[i * 2 + 0]; - U8 alpha = ((U8*)pixels)[i * 2 + 1]; + U32 pixel_count = (U32)(width * height); + for (U32 i = 0; i < pixel_count; i++) + { + U8* pix = (U8*)&scratch[i]; + pix[0] = pix[1] = pix[2] = 0; + pix[3] = ((U8*)pixels)[i]; + } - U8* pix = (U8*)&scratch[i]; - pix[0] = pix[1] = pix[2] = lum; - pix[3] = alpha; + pixels = scratch.get(); } - } - pixformat = GL_RGBA; - intformat = GL_RGBA8; - } + pixformat = GL_RGBA; + intformat = GL_RGBA8; + } - if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE) - { //GL_LUMINANCE_ALPHA is deprecated, convert to RGB - if (pixels != nullptr) - { - use_scratch = true; - scratch = new(std::nothrow) U32[width * height]; - if (!scratch) + if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE) + { //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA + if (pixels != nullptr) { - LLError::LLUserWarningMsg::showOutOfMemory(); - LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32)) - << " bytes for a manual image W" << width << " H" << height << LL_ENDL; + scratch.reset(new(std::nothrow) U32[width * height]); + if (!scratch) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32)) + << " bytes for a manual image W" << width << " H" << height << LL_ENDL; + } + + U32 pixel_count = (U32)(width * height); + for (U32 i = 0; i < pixel_count; i++) + { + U8 lum = ((U8*)pixels)[i * 2 + 0]; + U8 alpha = ((U8*)pixels)[i * 2 + 1]; + + U8* pix = (U8*)&scratch[i]; + pix[0] = pix[1] = pix[2] = lum; + pix[3] = alpha; + } + + pixels = scratch.get(); } - U32 pixel_count = (U32)(width * height); - for (U32 i = 0; i < pixel_count; i++) + pixformat = GL_RGBA; + intformat = GL_RGBA8; + } + + if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE) + { //GL_LUMINANCE_ALPHA is deprecated, convert to RGB + if (pixels != nullptr) { - U8 lum = ((U8*)pixels)[i]; + scratch.reset(new(std::nothrow) U32[width * height]); + if (!scratch) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32)) + << " bytes for a manual image W" << width << " H" << height << LL_ENDL; + } + + U32 pixel_count = (U32)(width * height); + for (U32 i = 0; i < pixel_count; i++) + { + U8 lum = ((U8*)pixels)[i]; + + U8* pix = (U8*)&scratch[i]; + pix[0] = pix[1] = pix[2] = lum; + pix[3] = 255; + } - U8* pix = (U8*)&scratch[i]; - pix[0] = pix[1] = pix[2] = lum; - pix[3] = 255; + pixels = scratch.get(); } + pixformat = GL_RGBA; + intformat = GL_RGB8; } - pixformat = GL_RGBA; - intformat = GL_RGB8; } } @@ -1326,6 +1371,14 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt { switch (intformat) { + case GL_RED: + case GL_R8: + intformat = GL_COMPRESSED_RED; + break; + case GL_RG: + case GL_RG8: + intformat = GL_COMPRESSED_RG; + break; case GL_RGB: case GL_RGB8: intformat = GL_COMPRESSED_RGB; @@ -1354,12 +1407,8 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt case GL_ALPHA8: intformat = GL_COMPRESSED_ALPHA; break; - case GL_RED: - case GL_R8: - intformat = GL_COMPRESSED_RED; - break; default: - LL_WARNS() << "Could not compress format: " << std::hex << intformat << LL_ENDL; + LL_WARNS() << "Could not compress format: " << std::hex << intformat << std::dec << LL_ENDL; break; } } @@ -1375,7 +1424,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt if (!use_sub_image) { LL_PROFILE_ZONE_NAMED("glTexImage2D alloc + copy"); - glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels); + glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, pixels); } else { @@ -1385,7 +1434,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, nullptr); } - U8* src = (U8*)(use_scratch ? scratch : pixels); + U8* src = (U8*)(pixels); if (src) { LL_PROFILE_ZONE_NAMED("glTexImage2D copy"); @@ -1395,11 +1444,6 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt alloc_tex_image(width, height, intformat, 1); } stop_glerror(); - - if (use_scratch) - { - delete[] scratch; - } } //create an empty GL texture: just create a texture name diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 9a8d935b89..a8b94bd5b0 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -101,9 +101,9 @@ public: static bool create(LLPointer& dest, const LLImageRaw* imageraw, bool usemipmaps = true); public: - LLImageGL(bool usemipmaps = true); - LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps = true); - LLImageGL(const LLImageRaw* imageraw, bool usemipmaps = true); + LLImageGL(bool usemipmaps = true, bool allow_compression = true); + LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps = true, bool allow_compression = true); + LLImageGL(const LLImageRaw* imageraw, bool usemipmaps = true, bool allow_compression = true); // For wrapping textures created via GL elsewhere with our API only. Use with caution. LLImageGL(LLGLuint mTexName, U32 components, LLGLenum target, LLGLint formatInternal, LLGLenum formatPrimary, LLGLenum formatType, LLTexUnit::eTextureAddressMode addressMode); @@ -203,7 +203,7 @@ public: LLGLenum getTexTarget()const { return mTarget; } - void init(bool usemipmaps); + void init(bool usemipmaps, bool allow_compression); virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors void setNeedsAlphaAndPickMask(bool need_mask); -- cgit v1.2.3 From 1cc1872c76de0d5f5d6c04c4b510367f9f002d97 Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Thu, 22 Aug 2024 15:59:15 +0200 Subject: #2393 BugSplat Crash #1504586: LLRenderTarget::getTexture(483) --- indra/llrender/llrendertarget.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index f700201ace..21a0820d32 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -475,12 +475,10 @@ void LLRenderTarget::clear(U32 mask_in) U32 LLRenderTarget::getTexture(U32 attachment) const { - if (attachment > mTex.size()-1) - { - LL_ERRS() << "Invalid attachment index." << LL_ENDL; - } - if (mTex.empty()) + if (attachment >= mTex.size()) { + LL_WARNS() << "Invalid attachment index " << attachment << " for size " << mTex.size() << LL_ENDL; + llassert(false); return 0; } return mTex[attachment]; -- cgit v1.2.3 From cbca17825614d18a96994c94ec0c38e9d8e812cf Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Sat, 24 Aug 2024 00:55:32 -0400 Subject: Add Contrast Adaptive Sharpening post process effect(#2399) --- indra/llrender/llglslshader.cpp | 46 +++++++++++++++++++++++++++++++++++++++++ indra/llrender/llglslshader.h | 2 ++ 2 files changed, 48 insertions(+) (limited to 'indra/llrender') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index e76a30a954..daa768e8ab 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -1552,6 +1552,34 @@ void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v) } } +void LLGLSLShader::uniform4uiv(U32 index, U32 count, const GLuint* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + llassert(sCurBoundShaderPtr == this); + + if (mProgramObject) + { + if (mUniform.size() <= index) + { + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << index << LL_ENDL; + llassert(false); + return; + } + + if (mUniform[index] >= 0) + { + const auto& iter = mValue.find(mUniform[index]); + LLVector4 vec((F32)v[0], (F32)v[1], (F32)v[2], (F32)v[3]); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + glUniform4uiv(mUniform[index], count, v); + mValue[mUniform[index]] = vec; + } + } + } +} + void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; @@ -1886,6 +1914,24 @@ void LLGLSLShader::uniform4fv(const LLStaticHashedString& uniform, U32 count, co } } +void LLGLSLShader::uniform4uiv(const LLStaticHashedString& uniform, U32 count, const GLuint* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + LLVector4 vec((F32)v[0], (F32)v[1], (F32)v[2], (F32)v[3]); + const auto& iter = mValue.find(location); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + glUniform4uiv(location, count, v); + mValue[location] = vec; + } + } +} + void LLGLSLShader::uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat* v) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 86e5625dca..f3c41cd819 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -208,6 +208,7 @@ public: void uniform2fv(U32 index, U32 count, const GLfloat* v); void uniform3fv(U32 index, U32 count, const GLfloat* v); void uniform4fv(U32 index, U32 count, const GLfloat* v); + void uniform4uiv(U32 index, U32 count, const GLuint* v); void uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j); void uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v); void uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v); @@ -223,6 +224,7 @@ public: void uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); void uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); void uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); + void uniform4uiv(const LLStaticHashedString& uniform, U32 count, const GLuint* v); void uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat* v); void setMinimumAlpha(F32 minimum); -- cgit v1.2.3 From 2ca193ce468cd4420e0ed47a7991661d1b1ca635 Mon Sep 17 00:00:00 2001 From: Rye Cogtail Date: Fri, 23 Aug 2024 22:06:28 -0400 Subject: Improve FXAA quality and performance when GL version is greater then 4 Adds gather4 support under GLSL 4.0+ --- indra/llrender/llshadermgr.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 512ef340f9..e9608491a4 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -595,8 +595,6 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev extra_code_text[extra_code_count++] = strdup("precision highp float;\n"); } } - - extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n"); } // Use alpha float to store bit flags -- cgit v1.2.3 From 436e986893d6eb9de1c4531540e6e2afe8ec06cb Mon Sep 17 00:00:00 2001 From: Rye Cogtail Date: Fri, 23 Aug 2024 22:05:34 -0400 Subject: Fix mac crash on startup due to missing types from enum --- indra/llrender/llimagegl.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index d5f7949051..03ac10c00a 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -316,8 +316,12 @@ S32 LLImageGL::dataFormatBits(S32 dataformat) case GL_RG16F: return 32; case GL_RGB16F: return 48; case GL_RGBA16F: return 64; + case GL_R32F: return 32; + case GL_RG32F: return 64; + case GL_RGB32F: return 96; + case GL_RGBA32F: return 128; default: - LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL; + LL_ERRS() << "LLImageGL::Unknown format: " << std::hex << dataformat << std::dec << LL_ENDL; return 0; } } @@ -367,7 +371,7 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat) case GL_SRGB_ALPHA: return 4; case GL_BGRA: return 4; // Used for QuickTime media textures on the Mac default: - LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL; + LL_ERRS() << "LLImageGL::Unknown format: " << std::hex << dataformat << std::dec << LL_ENDL; return 0; } } -- cgit v1.2.3 From 8406d1052c70d1d9f964ec86f6f5468aa9f57bb1 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 27 Aug 2024 11:53:54 -0500 Subject: #2428 Fix for crash when applying PBR material (#2430) Also attempt to fix some occasional bad texture memory tracking. --- indra/llrender/llimagegl.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 058afa0cf2..e4b176ff69 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -70,12 +70,15 @@ static U64 sTextureBytes = 0; void LLImageGLMemory::alloc_tex_image(U32 width, U32 height, U32 pixformat) { U32 texUnit = gGL.getCurrentTexUnitIndex(); + llassert(texUnit == 0); // allocations should always be done on tex unit 0 U32 texName = gGL.getTexUnit(texUnit)->getCurrTexture(); U64 size = LLImageGL::dataFormatBytes(pixformat, width, height); llassert(size >= 0); sTexMemMutex.lock(); + + // it is a precondition that no existing allocation exists for this texture llassert(sTextureAllocs.find(texName) == sTextureAllocs.end()); sTextureAllocs[texName] = size; @@ -89,7 +92,7 @@ void LLImageGLMemory::free_tex_image(U32 texName) { sTexMemMutex.lock(); auto iter = sTextureAllocs.find(texName); - if (iter != sTextureAllocs.end()) + if (iter != sTextureAllocs.end()) // sometimes a texName will be "freed" before allocated (e.g. first call to setManualImage for a given texName) { llassert(iter->second <= sTextureBytes); // sTextureBytes MUST NOT go below zero @@ -114,6 +117,7 @@ void LLImageGLMemory::free_tex_images(U32 count, const U32* texNames) void LLImageGLMemory::free_cur_tex_image() { U32 texUnit = gGL.getCurrentTexUnitIndex(); + llassert(texUnit == 0); // frees should always be done on tex unit 0 U32 texName = gGL.getTexUnit(texUnit)->getCurrTexture(); free_tex_image(texName); } @@ -1215,8 +1219,8 @@ void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures) if (!sFreeList[idx].empty()) { - glDeleteTextures((GLsizei) sFreeList[idx].size(), sFreeList[idx].data()); free_tex_images((GLsizei) sFreeList[idx].size(), sFreeList[idx].data()); + glDeleteTextures((GLsizei)sFreeList[idx].size(), sFreeList[idx].data()); sFreeList[idx].resize(0); } } @@ -2405,7 +2409,7 @@ bool LLImageGL::scaleDown(S32 desired_discard) { // use a PBO to downscale the texture U64 size = getBytes(desired_discard); llassert(size <= 2048 * 2048 * 4); // we shouldn't be using this method to downscale huge textures, but it'll work - gGL.getTexUnit(0)->bind(this); + gGL.getTexUnit(0)->bind(this, false, true); if (sScratchPBO == 0) { -- cgit v1.2.3 From f8d48f6a29f312724b826806fdc2f9b5ed85fd13 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 28 Aug 2024 14:49:13 -0500 Subject: #2432 Restore default nametag behavior. (#2444) After instrumenting nametags some more, really UI rendering performance improvements should just focus on LLFontGL::render --- indra/llrender/llgl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 7959b3bb57..c14efe8ab4 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -2742,7 +2742,7 @@ LLGLDepthTest::LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled, G : mPrevDepthEnabled(sDepthEnabled), mPrevDepthFunc(sDepthFunc), mPrevWriteEnabled(sWriteEnabled) { stop_glerror(); - + LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; checkState(); if (!depth_enabled) @@ -2775,6 +2775,7 @@ LLGLDepthTest::LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled, G LLGLDepthTest::~LLGLDepthTest() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; checkState(); if (sDepthEnabled != mPrevDepthEnabled ) { -- cgit v1.2.3 From 3a7374892945a233a9eaa3a88c94a984873373d3 Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Thu, 29 Aug 2024 15:56:28 -0400 Subject: Remove dead texunit colorspace conversion code --- indra/llrender/llglslshader.cpp | 14 ++++++-------- indra/llrender/llglslshader.h | 8 ++++---- indra/llrender/llrender.cpp | 18 ++---------------- indra/llrender/llrender.h | 5 ----- indra/llrender/llrendertarget.cpp | 1 - 5 files changed, 12 insertions(+), 34 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index daa768e8ab..a157bfee21 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -1087,17 +1087,17 @@ void LLGLSLShader::unbind(void) sCurBoundShaderPtr = NULL; } -S32 LLGLSLShader::bindTexture(const std::string& uniform, LLTexture* texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace) +S32 LLGLSLShader::bindTexture(const std::string& uniform, LLTexture* texture, LLTexUnit::eTextureType mode) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; S32 channel = 0; channel = getUniformLocation(uniform); - return bindTexture(channel, texture, mode, colorspace); + return bindTexture(channel, texture, mode); } -S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace) +S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextureType mode) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; @@ -1113,7 +1113,6 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextu if (uniform > -1) { gGL.getTexUnit(uniform)->bindFast(texture); - gGL.getTexUnit(uniform)->setTextureColorSpace(colorspace); } return uniform; @@ -1194,7 +1193,7 @@ S32 LLGLSLShader::getTextureChannel(S32 uniform) const return mTexture[uniform]; } -S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space) +S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; @@ -1211,12 +1210,11 @@ S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTex { gGL.getTexUnit(index)->activate(); gGL.getTexUnit(index)->enable(mode); - gGL.getTexUnit(index)->setTextureColorSpace(space); } return index; } -S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space) +S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; @@ -1229,7 +1227,7 @@ S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTe S32 index = mTexture[uniform]; if (index != -1 && gGL.getTexUnit(index)->getCurrType() != LLTexUnit::TT_NONE) { - if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode && gGL.getTexUnit(index)->getCurrColorSpace() != space) + if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode) { if (gDebugSession) { diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index f3c41cd819..913feb6a3f 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -249,16 +249,16 @@ public: //if given texture uniform is active in the shader, //the corresponding channel will be active upon return //returns channel texture is enabled in from [0-MAX) - S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR); - S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR); + S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); + S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); // get the texture channel of the given uniform, or -1 if uniform is not used as a texture S32 getTextureChannel(S32 uniform) const; // bindTexture returns the texture unit we've bound the texture to. // You can reuse the return value to unbind a texture when required. - S32 bindTexture(const std::string& uniform, LLTexture* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR); - S32 bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR); + S32 bindTexture(const std::string& uniform, LLTexture* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); + S32 bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); S32 bindTexture(const std::string& uniform, LLRenderTarget* texture, bool depth = false, LLTexUnit::eTextureFilterOptions mode = LLTexUnit::TFO_BILINEAR); S32 bindTexture(S32 uniform, LLRenderTarget* texture, bool depth = false, LLTexUnit::eTextureFilterOptions mode = LLTexUnit::TFO_BILINEAR, U32 index = 0); S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 1301d325a0..3572419a7a 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -115,7 +115,7 @@ static const GLenum sGLBlendFactor[] = LLTexUnit::LLTexUnit(S32 index) : mCurrTexType(TT_NONE), - mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0), mTexColorSpace(TCS_LINEAR), + mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0), mHasMipMaps(false), mIndex(index) { @@ -145,8 +145,6 @@ void LLTexUnit::refreshState(void) { glBindTexture(GL_TEXTURE_2D, 0); } - - setTextureColorSpace(mTexColorSpace); } void LLTexUnit::activate(void) @@ -241,7 +239,6 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind) setTextureAddressMode(gl_tex->mAddressMode); setTextureFilteringOption(gl_tex->mFilterOption); } - setTextureColorSpace(mTexColorSpace); } } else @@ -318,7 +315,6 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind, S32 setTextureFilteringOption(texture->mFilterOption); stop_glerror(); } - setTextureColorSpace(mTexColorSpace); } stop_glerror(); @@ -354,7 +350,6 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap) setTextureAddressMode(cubeMap->mImages[0]->mAddressMode); setTextureFilteringOption(cubeMap->mImages[0]->mFilterOption); } - setTextureColorSpace(mTexColorSpace); return true; } else @@ -403,7 +398,6 @@ bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips) mCurrTexture = texture; glBindTexture(sGLTextureType[type], texture); mHasMipMaps = hasMips; - setTextureColorSpace(mTexColorSpace); } return true; } @@ -424,8 +418,6 @@ void LLTexUnit::unbind(eTextureType type) { mCurrTexture = 0; - // Always make sure our texture color space is reset to linear. SRGB sampling should be opt-in in the vast majority of cases. Also prevents color space "popping". - mTexColorSpace = TCS_LINEAR; if (type == LLTexUnit::TT_TEXTURE) { glBindTexture(sGLTextureType[type], sWhiteTexture); @@ -447,8 +439,6 @@ void LLTexUnit::unbindFast(eTextureType type) { mCurrTexture = 0; - // Always make sure our texture color space is reset to linear. SRGB sampling should be opt-in in the vast majority of cases. Also prevents color space "popping". - mTexColorSpace = TCS_LINEAR; if (type == LLTexUnit::TT_TEXTURE) { glBindTexture(sGLTextureType[type], sWhiteTexture); @@ -642,11 +632,6 @@ void LLTexUnit::debugTextureUnit(void) } } -void LLTexUnit::setTextureColorSpace(eTextureColorSpace space) -{ - mTexColorSpace = space; -} - LLLightState::LLLightState(S32 index) : mIndex(index), mEnabled(false), @@ -1634,6 +1619,7 @@ void LLRender::flush() { HBXXH64 hash; + U32 attribute_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask; { diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 010ab122b6..4aa33b7427 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -219,17 +219,12 @@ public: void setHasMipMaps(bool hasMips) { mHasMipMaps = hasMips; } - void setTextureColorSpace(eTextureColorSpace space); - - eTextureColorSpace getCurrColorSpace() { return mTexColorSpace; } - protected: friend class LLRender; S32 mIndex; U32 mCurrTexture; eTextureType mCurrTexType; - eTextureColorSpace mTexColorSpace; S32 mCurrColorScale; S32 mCurrAlphaScale; bool mHasMipMaps; diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 21a0820d32..38bc5ff331 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -509,7 +509,6 @@ void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilt } gGL.getTexUnit(channel)->setTextureFilteringOption(filter_options); - gGL.getTexUnit(channel)->setTextureColorSpace(isSRGB ? LLTexUnit::TCS_SRGB : LLTexUnit::TCS_LINEAR); } void LLRenderTarget::flush() -- cgit v1.2.3 From 958afaa7a7bfb1217bbffee3fe562f21901277ac Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Tue, 27 Aug 2024 22:47:32 -0400 Subject: Integrate SMAA and rework post process chain for better visual quality Add SMAA buffer generation passes Add quality levels for both FXAA and SMAA Separate gamma correction and tonemapping for effects that require linear-but-tonemapped inputs Move application of noise to final render pass to screen to avoid damaging other post process effects --- indra/llrender/llglslshader.h | 4 ++++ indra/llrender/llrender.cpp | 1 - indra/llrender/llshadermgr.cpp | 14 ++++++++++++++ indra/llrender/llshadermgr.h | 5 +++++ 4 files changed, 23 insertions(+), 1 deletion(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 913feb6a3f..27c8f0b7d0 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -241,6 +241,10 @@ public: void clearPermutations(); void addPermutation(std::string name, std::string value); + void addPermutations(const std::map& defines) + { + mDefines.insert(defines.begin(), defines.end()); + } void removePermutation(std::string name); void addConstant(const LLGLSLShader::eShaderConsts shader_const); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 3572419a7a..7a52f9cfb5 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1619,7 +1619,6 @@ void LLRender::flush() { HBXXH64 hash; - U32 attribute_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask; { diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index e9608491a4..150277c8df 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -597,6 +597,15 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev } } + if (type == GL_FRAGMENT_SHADER) + { + extra_code_text[extra_code_count++] = strdup("#define FRAGMENT_SHADER 1\n"); + } + else + { + extra_code_text[extra_code_count++] = strdup("#define VERTEX_SHADER 1\n"); + } + // Use alpha float to store bit flags // See: C++: addDeferredAttachment(), shader: frag_data[2] extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_SKIP_ATMOS 0.0 \n"); // atmo kill @@ -1468,6 +1477,11 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("debug_normal_draw_length"); + mReservedUniforms.push_back("edgesTex"); + mReservedUniforms.push_back("areaTex"); + mReservedUniforms.push_back("searchTex"); + mReservedUniforms.push_back("blendTex"); + llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS); std::set dupe_check; diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 2b76ef664b..0eb9db6715 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -332,6 +332,11 @@ public: DEBUG_NORMAL_DRAW_LENGTH, // "debug_normal_draw_length" + SMAA_EDGE_TEX, // "edgesTex" + SMAA_AREA_TEX, // "areaTex" + SMAA_SEARCH_TEX, // "searchTex" + SMAA_BLEND_TEX, // "blendTex" + END_RESERVED_UNIFORMS } eGLSLReservedUniforms; // clang-format on -- cgit v1.2.3 From 4ae1de1f8a78d795958d67afab8356f9a13f707d Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 28 Aug 2024 23:05:58 +0300 Subject: viewer#2411 LLFontGL::render optimizations --- indra/llrender/CMakeLists.txt | 2 + indra/llrender/llfontgl.cpp | 124 +++++++++++++++++---- indra/llrender/llfontgl.h | 15 ++- indra/llrender/llfontvertexbuffer.cpp | 157 +++++++++++++++++++++++++++ indra/llrender/llfontvertexbuffer.h | 85 +++++++++++++++ indra/llrender/llrender.cpp | 197 ++++++++++++++++++++++++++++------ indra/llrender/llrender.h | 10 ++ 7 files changed, 538 insertions(+), 52 deletions(-) create mode 100644 indra/llrender/llfontvertexbuffer.cpp create mode 100644 indra/llrender/llfontvertexbuffer.h (limited to 'indra/llrender') diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index 7f881c8bb3..ccff7c7a8c 100644 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -17,6 +17,7 @@ set(llrender_SOURCE_FILES llfontfreetype.cpp llfontfreetypesvg.cpp llfontgl.cpp + llfontvertexbuffer.cpp llfontregistry.cpp llgl.cpp llglslshader.cpp @@ -43,6 +44,7 @@ set(llrender_HEADER_FILES llcubemap.h llcubemaparray.h llfontgl.h + llfontvertexbuffer.h llfontfreetype.h llfontfreetypesvg.h llfontbitmapcache.h diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index b6cdb81b33..481e35c16a 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -34,6 +34,7 @@ #include "llfontbitmapcache.h" #include "llfontregistry.h" #include "llgl.h" +#include "llglslshader.h" #include "llimagegl.h" #include "llrender.h" #include "llstl.h" @@ -41,6 +42,7 @@ #include "lltexture.h" #include "lldir.h" #include "llstring.h" +#include "llvertexbuffer.h" // Third party library includes #include @@ -143,7 +145,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRectf& rec S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, - ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, bool use_ellipses, bool use_color) const + ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, bool use_ellipses, bool use_color, + std::list *buffer_list) const { LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; @@ -157,6 +160,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons return 0; } + gGL.flush(); // deliberately empty pending verts gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); @@ -270,10 +274,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons const LLFontGlyphInfo* next_glyph = NULL; - const S32 GLYPH_BATCH_SIZE = 30; - LLVector3 vertices[GLYPH_BATCH_SIZE * 4]; - LLVector2 uvs[GLYPH_BATCH_SIZE * 4]; - LLColor4U colors[GLYPH_BATCH_SIZE * 4]; + static constexpr S32 GLYPH_BATCH_SIZE = 30; + static thread_local LLVector3 vertices[GLYPH_BATCH_SIZE * 4]; + static thread_local LLVector2 uvs[GLYPH_BATCH_SIZE * 4]; + static thread_local LLColor4U colors[GLYPH_BATCH_SIZE * 4]; LLColor4U text_color(color); // Preserve the transparency to render fading emojis in fading text (e.g. @@ -282,6 +286,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons std::pair bitmap_entry = std::make_pair(EFontGlyphType::Grayscale, -1); S32 glyph_count = 0; + S32 buffer_count = 0; + LLVertexBuffer* vb; + LLImageGL* font_image = nullptr; for (i = begin_offset; i < begin_offset + length; i++) { llwchar wch = wstr[i]; @@ -305,16 +312,35 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons // otherwise the queued glyphs will be taken from wrong textures. if (glyph_count > 0) { - gGL.begin(LLRender::QUADS); + if (buffer_list) { + vb = gGL.beginNoCache(LLRender::QUADS, buffer_count); + if (vb) + { + buffer_list->emplace_back(vb, font_image, LLRender::QUADS, buffer_count); + } + gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); + + vb = gGL.getBuffer(buffer_count); // instead of endNoCache to draw now + if (vb) + { + buffer_list->emplace_back(vb, font_image, LLRender::QUADS, buffer_count); + } + } + else + { + gGL.begin(LLRender::QUADS); + { + gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); + } + gGL.end(); } - gGL.end(); glyph_count = 0; } bitmap_entry = next_bitmap_entry; - LLImageGL* font_image = font_bitmap_cache->getImageGL(bitmap_entry.first, bitmap_entry.second); + font_image = font_bitmap_cache->getImageGL(bitmap_entry.first, bitmap_entry.second); gGL.getTexUnit(0)->bind(font_image); } @@ -338,11 +364,28 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons if (glyph_count >= GLYPH_BATCH_SIZE) { - gGL.begin(LLRender::QUADS); + if (buffer_list) { + vb = gGL.beginNoCache(LLRender::QUADS, buffer_count); + if (vb) + { + buffer_list->emplace_back(vb, font_image, LLRender::QUADS, buffer_count); + } gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); + vb = gGL.endNoCache(buffer_count); + if (vb) + { + buffer_list->emplace_back(vb, font_image, LLRender::QUADS, buffer_count); + } + } + else + { + gGL.begin(LLRender::QUADS); + { + gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); + } + gGL.end(); } - gGL.end(); glyph_count = 0; } @@ -376,11 +419,28 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons cur_render_y = cur_y; } - gGL.begin(LLRender::QUADS); + if (buffer_list) { + vb = gGL.beginNoCache(LLRender::QUADS, buffer_count); + if (vb) + { + buffer_list->emplace_back(vb, font_image, LLRender::QUADS, buffer_count); + } gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); + vb = gGL.endNoCache(buffer_count); + if (vb) + { + buffer_list->emplace_back(vb, font_image, LLRender::QUADS, buffer_count); + } + } + else + { + gGL.begin(LLRender::QUADS); + { + gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); + } + gGL.end(); } - gGL.end(); if (right_x) @@ -394,15 +454,42 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons F32 descender = (F32)llfloor(mFontFreetype->getDescenderHeight()); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.begin(LLRender::LINES); - gGL.vertex2f(start_x, cur_y - descender); - gGL.vertex2f(cur_x, cur_y - descender); - gGL.end(); + if (buffer_list) + { + vb = gGL.beginNoCache(LLRender::LINES, buffer_count); + if (vb) + { + buffer_list->emplace_back(vb, nullptr, LLRender::QUADS, buffer_count); + } + + gGL.vertex2f(start_x, cur_y - descender); + gGL.vertex2f(cur_x, cur_y - descender); + + vb = gGL.getBuffer(buffer_count); + if (vb) + { + buffer_list->emplace_back(vb, nullptr, LLRender::LINES, buffer_count); + } + } + else + { + gGL.begin(LLRender::LINES); + gGL.vertex2f(start_x, cur_y - descender); + gGL.vertex2f(cur_x, cur_y - descender); + gGL.end(); + } + } + else if (buffer_list) + { + vb = gGL.getBuffer(buffer_count); + if (vb) + { + buffer_list->emplace_back(vb, font_image, gGL.getMode(), buffer_count); + } } if (draw_ellipses) { - // recursively render ellipses at end of string // we've already reserved enough room gGL.pushUIMatrix(); @@ -417,7 +504,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons S32_MAX, max_pixels, right_x, false, - use_color); + use_color, + buffer_list); gGL.popUIMatrix(); } diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index de7529a583..5015601cf6 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -33,6 +33,7 @@ #include "llimagegl.h" #include "llpointer.h" #include "llrect.h" +#include "llvertexbuffer.h" #include "v2math.h" class LLColor4; @@ -42,6 +43,7 @@ class LLFontFreetype; // Structure used to store previously requested fonts. class LLFontRegistry; +class LLVertexBuffer; class LLFontGL { @@ -79,6 +81,16 @@ public: DROP_SHADOW_SOFT }; + struct LLVertexBufferData + { + LLVertexBufferData() : mBuffer(nullptr), mImage(nullptr), mMode(0), mCount(0) {} + LLVertexBufferData(LLVertexBuffer* buffer, LLImageGL* image, U8 mode, U32 count) : mBuffer(buffer), mImage(image), mMode(mode), mCount(count) {} + LLPointer mBuffer; + LLPointer mImage; // might be a better idea to store + U8 mMode; + U32 mCount; + }; + LLFontGL(); ~LLFontGL(); @@ -119,7 +131,8 @@ public: S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX, F32* right_x=NULL, bool use_ellipses = false, - bool use_color = true) const; + bool use_color = true, + std::list* buffer_list = nullptr) const; S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const; diff --git a/indra/llrender/llfontvertexbuffer.cpp b/indra/llrender/llfontvertexbuffer.cpp new file mode 100644 index 0000000000..3ff0771795 --- /dev/null +++ b/indra/llrender/llfontvertexbuffer.cpp @@ -0,0 +1,157 @@ +/** + * @file llfontvertexbuffer.cpp + * @brief Buffer storage for font rendering. + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llfontvertexbuffer.h" + +#include "llvertexbuffer.h" + + +LLFontVertexBuffer::LLFontVertexBuffer(bool track_changes) +: mTrackStringChanges(track_changes) +{ +} + +LLFontVertexBuffer::~LLFontVertexBuffer() +{ + reset(); +} + +void LLFontVertexBuffer::reset() +{ + mBufferList.clear(); +} + +S32 LLFontVertexBuffer::render( + const LLFontGL* fontp, + const LLWString& text, + S32 begin_offset, + F32 x, F32 y, + const LLColor4& color, + LLFontGL::HAlign halign, LLFontGL::VAlign valign, + U8 style, LLFontGL::ShadowType shadow, + S32 max_chars , S32 max_pixels, + F32* right_x, + bool use_ellipses, + bool use_color ) +{ + if (mBufferList.empty()) + { + genBuffers(fontp, text, begin_offset, x, y, color, halign, valign, + style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color); + } + else if (mLastX != x || mLastY != y || mLastColor != color) // always track position and alphs + { + genBuffers(fontp, text, begin_offset, x, y, color, halign, valign, + style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color); + } + else if (true //mTrackStringChanges + && (mLastOffset != begin_offset + || mLastMaxChars != max_chars + || mLastMaxPixels != max_pixels + || mLastStringHash != sStringHasher._Do_hash(text))) // todo, track all parameters? + { + genBuffers(fontp, text, begin_offset, x, y, color, halign, valign, + style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color); + } + else + { + + gGL.flush(); // deliberately empty pending verts + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + gGL.pushUIMatrix(); + + gGL.loadUIIdentity(); + + // Depth translation, so that floating text appears 'in-world' + // and is correctly occluded. + gGL.translatef(0.f, 0.f, LLFontGL::sCurDepth); + + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + for (auto &buf_data : mBufferList) + { + if (buf_data.mImage) + { + gGL.getTexUnit(0)->bind(buf_data.mImage); + } + else + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + buf_data.mBuffer->setBuffer(); + + if (LLRender::sGLCoreProfile && buf_data.mMode == LLRender::QUADS) + { + buf_data.mBuffer->drawArrays(LLRender::TRIANGLES, 0, buf_data.mCount); + } + else + { + buf_data.mBuffer->drawArrays(buf_data.mMode, 0, buf_data.mCount); + } + } + if (right_x) + { + *right_x = mLastRightX; + } + + gGL.popUIMatrix(); + } + return mChars; +} + +void LLFontVertexBuffer::genBuffers( + const LLFontGL* fontp, + const LLWString& text, + S32 begin_offset, + F32 x, F32 y, + const LLColor4& color, + LLFontGL::HAlign halign, LLFontGL::VAlign valign, + U8 style, LLFontGL::ShadowType shadow, + S32 max_chars, S32 max_pixels, + F32* right_x, + bool use_ellipses, + bool use_color) +{ + mBufferList.clear(); + mChars = fontp->render(text, begin_offset, x, y, color, halign, valign, + style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color, &mBufferList); + + mLastOffset = begin_offset; + mLastMaxChars = max_chars; + mLastMaxPixels = max_pixels; + mLastStringHash = sStringHasher._Do_hash(text); + mLastX = x; + mLastY = y; + mLastColor = color; + + if (right_x) + { + mLastRightX = *right_x; + } +} + diff --git a/indra/llrender/llfontvertexbuffer.h b/indra/llrender/llfontvertexbuffer.h new file mode 100644 index 0000000000..bd42cf6c2d --- /dev/null +++ b/indra/llrender/llfontvertexbuffer.h @@ -0,0 +1,85 @@ +/** + * @file llfontgl.h + * @author Andrii Kleshchev + * @brief Buffer storage for font rendering. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFONTVERTEXBUFFER_H +#define LL_LLFONTVERTEXBUFFER_H + +#include "llfontgl.h" + +class LLVertexBuffer; + +class LLFontVertexBuffer +{ +public: + LLFontVertexBuffer(bool track_changes = true); + ~LLFontVertexBuffer(); + + void reset(); + + S32 render(const LLFontGL* fontp, + const LLWString& text, + S32 begin_offset, + F32 x, F32 y, + const LLColor4& color, + LLFontGL::HAlign halign = LLFontGL::LEFT, LLFontGL::VAlign valign = LLFontGL::BASELINE, + U8 style = LLFontGL::NORMAL, LLFontGL::ShadowType shadow = LLFontGL::NO_SHADOW, + S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX, + F32* right_x = NULL, + bool use_ellipses = false, + bool use_color = true); + +private: + + void genBuffers(const LLFontGL* fontp, + const LLWString& text, + S32 begin_offset, + F32 x, F32 y, + const LLColor4& color, + LLFontGL::HAlign halign, LLFontGL::VAlign valign, + U8 style, LLFontGL::ShadowType shadow, + S32 max_chars, S32 max_pixels, + F32* right_x, + bool use_ellipses, + bool use_color); + + + std::list mBufferList; + S32 mChars = 0; + S32 mLastOffset = 0; + S32 mLastMaxChars = 0; + S32 mLastMaxPixels = 0; + size_t mLastStringHash = 0; + F32 mLastX = 0.f; + F32 mLastY = 0.f; + LLColor4 mLastColor; + F32 mLastRightX = 0.f; + bool mTrackStringChanges = true; + + static std::hash sStringHasher; +}; + +#endif diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 7a52f9cfb5..8cd2d9cc15 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1570,6 +1570,51 @@ void LLRender::end() flush(); } } + +LLVertexBuffer* LLRender::beginNoCache(const GLuint& mode, S32& count) +{ + if (mode != mMode) + { + if (mode == LLRender::QUADS) + { + mQuadCycle = 1; + } + + if (mMode == LLRender::QUADS || + mMode == LLRender::LINES || + mMode == LLRender::TRIANGLES || + mMode == LLRender::POINTS) + { + return getBuffer(count); + } + else if (mCount != 0) + { + LL_ERRS() << "gGL.begin() called redundantly." << LL_ENDL; + } + mMode = mode; + } + return nullptr; +} + +LLVertexBuffer* LLRender::endNoCache(S32& count) +{ + if (mCount == 0) + { + return nullptr; + //IMM_ERRS << "GL begin and end called with no vertices specified." << LL_ENDL; + } + + if ((mMode != LLRender::QUADS && + mMode != LLRender::LINES && + mMode != LLRender::TRIANGLES && + mMode != LLRender::POINTS) || + mCount > 2048) + { + return getBuffer(count); + } + return nullptr; +} + void LLRender::flush() { STOP_GLERROR; @@ -1664,27 +1709,7 @@ void LLRender::flush() else { LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache miss"); - vb = new LLVertexBuffer(attribute_mask); - vb->allocateBuffer(count, 0); - - vb->setBuffer(); - - vb->setPositionData((LLVector4a*) mVerticesp.get()); - - if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0) - { - vb->setTexCoord0Data(mTexcoordsp.get()); - } - - if (attribute_mask & LLVertexBuffer::MAP_COLOR) - { - vb->setColorData(mColorsp.get()); - } - -#if LL_DARWIN - vb->unmapBuffer(); -#endif - vb->unbind(); + vb = genBuffer(attribute_mask, count); sVBCache[vhash] = { vb , std::chrono::steady_clock::now() }; @@ -1712,31 +1737,137 @@ void LLRender::flush() } } - vb->setBuffer(); + drawBuffer(vb, mMode, count); + } + else + { + // mBuffer is present in main thread and not present in an image thread + LL_ERRS() << "A flush call from outside main rendering thread" << LL_ENDL; + } + + resetStriders(count); + } +} + +LLVertexBuffer* LLRender::genBuffer(U32 attribute_mask, S32 count) +{ + LLVertexBuffer * vb = new LLVertexBuffer(attribute_mask); + vb->allocateBuffer(count, 0); + + vb->setBuffer(); + + vb->setPositionData((LLVector4a*)mVerticesp.get()); + + if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0) + { + vb->setTexCoord0Data(mTexcoordsp.get()); + } - if (mMode == LLRender::QUADS && sGLCoreProfile) + if (attribute_mask & LLVertexBuffer::MAP_COLOR) + { + vb->setColorData(mColorsp.get()); + } + +#if LL_DARWIN + vb->unmapBuffer(); +#endif + vb->unbind(); + + return vb; +} + +void LLRender::drawBuffer(LLVertexBuffer* vb, U32 mode, S32 count) +{ + vb->setBuffer(); + + if (mode == LLRender::QUADS && sGLCoreProfile) + { + vb->drawArrays(LLRender::TRIANGLES, 0, count); + mQuadCycle = 1; + } + else + { + vb->drawArrays(mode, 0, count); + } +} + +void LLRender::resetStriders(S32 count) +{ + mVerticesp[0] = mVerticesp[count]; + mTexcoordsp[0] = mTexcoordsp[count]; + mColorsp[0] = mColorsp[count]; + + mCount = 0; +} + +LLVertexBuffer* LLRender::getBuffer(S32 & count) +{ + STOP_GLERROR; + LLVertexBuffer *vb; + if (mCount > 0) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; + llassert(LLGLSLShader::sCurBoundShaderPtr != nullptr); + if (!mUIOffset.empty()) + { + sUICalls++; + sUIVerts += mCount; + } + + //store mCount in a local variable to avoid re-entrance (drawArrays may call flush) + count = mCount; + + if (mMode == LLRender::QUADS && !sGLCoreProfile) + { + if (mCount % 4 != 0) { - vb->drawArrays(LLRender::TRIANGLES, 0, count); - mQuadCycle = 1; + count -= (mCount % 4); + LL_WARNS() << "Incomplete quad requested." << LL_ENDL; } - else + } + + if (mMode == LLRender::TRIANGLES) + { + if (mCount % 3 != 0) { - vb->drawArrays(mMode, 0, count); + count -= (mCount % 3); + LL_WARNS() << "Incomplete triangle requested." << LL_ENDL; } } + + if (mMode == LLRender::LINES) + { + if (mCount % 2 != 0) + { + count -= (mCount % 2); + LL_WARNS() << "Incomplete line requested." << LL_ENDL; + } + } + + mCount = 0; + + if (mBuffer) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache miss"); + + U32 attribute_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask; + vb = genBuffer(attribute_mask, count); + drawBuffer(vb, mMode, count); + } else { // mBuffer is present in main thread and not present in an image thread LL_ERRS() << "A flush call from outside main rendering thread" << LL_ENDL; } - - mVerticesp[0] = mVerticesp[count]; - mTexcoordsp[0] = mTexcoordsp[count]; - mColorsp[0] = mColorsp[count]; - - mCount = 0; + resetStriders(count); } + else + { + count = 0; + } + + return vb; } void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 4aa33b7427..5f84a4a275 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -417,6 +417,12 @@ public: void begin(const GLuint& mode); void end(); + + LLVertexBuffer* beginNoCache(const GLuint& mode, S32& count); + LLVertexBuffer* endNoCache(S32& count); + LLVertexBuffer* getBuffer(S32& count); + U8 getMode() const { return mMode; } + void vertex2i(const GLint& x, const GLint& y); void vertex2f(const GLfloat& x, const GLfloat& y); void vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z); @@ -485,6 +491,10 @@ public: private: friend class LLLightState; + LLVertexBuffer* genBuffer(U32 attribute_mask, S32 count); + void drawBuffer(LLVertexBuffer* vb, U32 mode, S32 count); + void resetStriders(S32 count); + eMatrixMode mMatrixMode; U32 mMatIdx[NUM_MATRIX_MODES]; U32 mMatHash[NUM_MATRIX_MODES]; -- cgit v1.2.3 From a638d9610d9f369eca6dff74e8860ca466c253c7 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 29 Aug 2024 18:49:10 +0300 Subject: viewer#2411 LLFontGL::render optimizations #2 --- indra/llrender/llfontgl.cpp | 3 + indra/llrender/llfontvertexbuffer.cpp | 119 ++++++++++++++++++++++------------ indra/llrender/llfontvertexbuffer.h | 15 ++++- 3 files changed, 92 insertions(+), 45 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 481e35c16a..701ab4d060 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -490,6 +490,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons if (draw_ellipses) { + // signal a separate context + buffer_list->emplace_back(nullptr, nullptr, 0, 0); + // recursively render ellipses at end of string // we've already reserved enough room gGL.pushUIMatrix(); diff --git a/indra/llrender/llfontvertexbuffer.cpp b/indra/llrender/llfontvertexbuffer.cpp index 3ff0771795..c4b68c4a6c 100644 --- a/indra/llrender/llfontvertexbuffer.cpp +++ b/indra/llrender/llfontvertexbuffer.cpp @@ -53,7 +53,8 @@ S32 LLFontVertexBuffer::render( F32 x, F32 y, const LLColor4& color, LLFontGL::HAlign halign, LLFontGL::VAlign valign, - U8 style, LLFontGL::ShadowType shadow, + U8 style, + LLFontGL::ShadowType shadow, S32 max_chars , S32 max_pixels, F32* right_x, bool use_ellipses, @@ -64,62 +65,33 @@ S32 LLFontVertexBuffer::render( genBuffers(fontp, text, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color); } - else if (mLastX != x || mLastY != y || mLastColor != color) // always track position and alphs + else if (mLastX != x || mLastY != y + || mLastFont != fontp + || mLastColor != color // alphas change often + || mLastHalign != halign + || mLastValign != valign + || mLastOffset != begin_offset + || mLastMaxChars != max_chars + || mLastMaxPixels != max_pixels + || mLastStyle != style + || mLastShadow != shadow) // ex: buttons change shadow state { genBuffers(fontp, text, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color); } - else if (true //mTrackStringChanges - && (mLastOffset != begin_offset - || mLastMaxChars != max_chars - || mLastMaxPixels != max_pixels - || mLastStringHash != sStringHasher._Do_hash(text))) // todo, track all parameters? + else if (mTrackStringChanges && mLastStringHash != sStringHasher._Do_hash(text)) { genBuffers(fontp, text, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color); } else { + renderBuffers(); - gGL.flush(); // deliberately empty pending verts - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - gGL.pushUIMatrix(); - - gGL.loadUIIdentity(); - - // Depth translation, so that floating text appears 'in-world' - // and is correctly occluded. - gGL.translatef(0.f, 0.f, LLFontGL::sCurDepth); - - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - for (auto &buf_data : mBufferList) - { - if (buf_data.mImage) - { - gGL.getTexUnit(0)->bind(buf_data.mImage); - } - else - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - buf_data.mBuffer->setBuffer(); - - if (LLRender::sGLCoreProfile && buf_data.mMode == LLRender::QUADS) - { - buf_data.mBuffer->drawArrays(LLRender::TRIANGLES, 0, buf_data.mCount); - } - else - { - buf_data.mBuffer->drawArrays(buf_data.mMode, 0, buf_data.mCount); - } - } if (right_x) { *right_x = mLastRightX; } - - gGL.popUIMatrix(); } return mChars; } @@ -141,6 +113,7 @@ void LLFontVertexBuffer::genBuffers( mChars = fontp->render(text, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color, &mBufferList); + mLastFont = fontp; mLastOffset = begin_offset; mLastMaxChars = max_chars; mLastMaxPixels = max_pixels; @@ -148,6 +121,10 @@ void LLFontVertexBuffer::genBuffers( mLastX = x; mLastY = y; mLastColor = color; + mLastHalign = halign; + mLastValign = valign; + mLastStyle = style; + mLastShadow = shadow; if (right_x) { @@ -155,3 +132,61 @@ void LLFontVertexBuffer::genBuffers( } } +void render_buffers(LLFontVertexBuffer::buffer_list_t::iterator iter, LLFontVertexBuffer::buffer_list_t::iterator end) +{ + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + gGL.pushUIMatrix(); + + gGL.loadUIIdentity(); + + // Depth translation, so that floating text appears 'in-world' + // and is correctly occluded. + gGL.translatef(0.f, 0.f, LLFontGL::sCurDepth); + + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + while (iter != end) + { + if (iter->mBuffer == nullptr) + { + // elipses indicator + iter++; + break; + } + if (iter->mImage) + { + gGL.getTexUnit(0)->bind(iter->mImage); + } + else + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + iter->mBuffer->setBuffer(); + + if (LLRender::sGLCoreProfile && iter->mMode == LLRender::QUADS) + { + iter->mBuffer->drawArrays(LLRender::TRIANGLES, 0, iter->mCount); + } + else + { + iter->mBuffer->drawArrays(iter->mMode, 0, iter->mCount); + } + iter++; + } + + if (iter != end) + { + gGL.pushUIMatrix(); + render_buffers(iter, end); + gGL.popUIMatrix(); + } + + gGL.popUIMatrix(); +} + +void LLFontVertexBuffer::renderBuffers() +{ + gGL.flush(); // deliberately empty pending verts + render_buffers(mBufferList.begin(), mBufferList.end()); +} + diff --git a/indra/llrender/llfontvertexbuffer.h b/indra/llrender/llfontvertexbuffer.h index bd42cf6c2d..458b0a91bb 100644 --- a/indra/llrender/llfontvertexbuffer.h +++ b/indra/llrender/llfontvertexbuffer.h @@ -46,12 +46,14 @@ public: F32 x, F32 y, const LLColor4& color, LLFontGL::HAlign halign = LLFontGL::LEFT, LLFontGL::VAlign valign = LLFontGL::BASELINE, - U8 style = LLFontGL::NORMAL, LLFontGL::ShadowType shadow = LLFontGL::NO_SHADOW, + U8 style = LLFontGL::NORMAL, + LLFontGL::ShadowType shadow = LLFontGL::NO_SHADOW, S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX, F32* right_x = NULL, bool use_ellipses = false, bool use_color = true); + typedef std::list buffer_list_t; private: void genBuffers(const LLFontGL* fontp, @@ -60,15 +62,18 @@ private: F32 x, F32 y, const LLColor4& color, LLFontGL::HAlign halign, LLFontGL::VAlign valign, - U8 style, LLFontGL::ShadowType shadow, + U8 style, + LLFontGL::ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, bool use_ellipses, bool use_color); + void renderBuffers(); - std::list mBufferList; + buffer_list_t mBufferList; S32 mChars = 0; + const LLFontGL *mLastFont = nullptr; S32 mLastOffset = 0; S32 mLastMaxChars = 0; S32 mLastMaxPixels = 0; @@ -76,6 +81,10 @@ private: F32 mLastX = 0.f; F32 mLastY = 0.f; LLColor4 mLastColor; + LLFontGL::HAlign mLastHalign = LLFontGL::LEFT; + LLFontGL::VAlign mLastValign = LLFontGL::BASELINE; + U8 mLastStyle = LLFontGL::NORMAL; + LLFontGL::ShadowType mLastShadow = LLFontGL::NO_SHADOW; F32 mLastRightX = 0.f; bool mTrackStringChanges = true; -- cgit v1.2.3 From 5c64e5e13d9a75cac510aac3128fc6ee780ab243 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 30 Aug 2024 18:51:48 +0300 Subject: viewer#2411 LLFontGL::render optimizations #3 --- indra/llrender/llfontgl.cpp | 118 +++-------------------- indra/llrender/llfontgl.h | 15 +-- indra/llrender/llfontvertexbuffer.cpp | 75 +++++---------- indra/llrender/llfontvertexbuffer.h | 12 ++- indra/llrender/llrender.cpp | 175 +++++++++++++++++++++------------- indra/llrender/llrender.h | 9 +- indra/llrender/llvertexbuffer.cpp | 47 +++++++++ indra/llrender/llvertexbuffer.h | 31 ++++++ 8 files changed, 238 insertions(+), 244 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 701ab4d060..7d74bb3e46 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -42,7 +42,6 @@ #include "lltexture.h" #include "lldir.h" #include "llstring.h" -#include "llvertexbuffer.h" // Third party library includes #include @@ -145,8 +144,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRectf& rec S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, - ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, bool use_ellipses, bool use_color, - std::list *buffer_list) const + ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, bool use_ellipses, bool use_color) const { LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; @@ -160,7 +158,6 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons return 0; } - gGL.flush(); // deliberately empty pending verts gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); @@ -286,9 +283,6 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons std::pair bitmap_entry = std::make_pair(EFontGlyphType::Grayscale, -1); S32 glyph_count = 0; - S32 buffer_count = 0; - LLVertexBuffer* vb; - LLImageGL* font_image = nullptr; for (i = begin_offset; i < begin_offset + length; i++) { llwchar wch = wstr[i]; @@ -312,35 +306,16 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons // otherwise the queued glyphs will be taken from wrong textures. if (glyph_count > 0) { - if (buffer_list) + gGL.begin(LLRender::QUADS); { - vb = gGL.beginNoCache(LLRender::QUADS, buffer_count); - if (vb) - { - buffer_list->emplace_back(vb, font_image, LLRender::QUADS, buffer_count); - } - gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); - - vb = gGL.getBuffer(buffer_count); // instead of endNoCache to draw now - if (vb) - { - buffer_list->emplace_back(vb, font_image, LLRender::QUADS, buffer_count); - } - } - else - { - gGL.begin(LLRender::QUADS); - { - gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); - } - gGL.end(); } + gGL.end(); glyph_count = 0; } bitmap_entry = next_bitmap_entry; - font_image = font_bitmap_cache->getImageGL(bitmap_entry.first, bitmap_entry.second); + LLImageGL* font_image = font_bitmap_cache->getImageGL(bitmap_entry.first, bitmap_entry.second); gGL.getTexUnit(0)->bind(font_image); } @@ -364,28 +339,11 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons if (glyph_count >= GLYPH_BATCH_SIZE) { - if (buffer_list) + gGL.begin(LLRender::QUADS); { - vb = gGL.beginNoCache(LLRender::QUADS, buffer_count); - if (vb) - { - buffer_list->emplace_back(vb, font_image, LLRender::QUADS, buffer_count); - } gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); - vb = gGL.endNoCache(buffer_count); - if (vb) - { - buffer_list->emplace_back(vb, font_image, LLRender::QUADS, buffer_count); - } - } - else - { - gGL.begin(LLRender::QUADS); - { - gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); - } - gGL.end(); } + gGL.end(); glyph_count = 0; } @@ -418,29 +376,11 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons cur_render_x = cur_x; cur_render_y = cur_y; } - - if (buffer_list) + gGL.begin(LLRender::QUADS); { - vb = gGL.beginNoCache(LLRender::QUADS, buffer_count); - if (vb) - { - buffer_list->emplace_back(vb, font_image, LLRender::QUADS, buffer_count); - } gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); - vb = gGL.endNoCache(buffer_count); - if (vb) - { - buffer_list->emplace_back(vb, font_image, LLRender::QUADS, buffer_count); - } - } - else - { - gGL.begin(LLRender::QUADS); - { - gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); - } - gGL.end(); } + gGL.end(); if (right_x) @@ -454,45 +394,14 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons F32 descender = (F32)llfloor(mFontFreetype->getDescenderHeight()); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - if (buffer_list) - { - vb = gGL.beginNoCache(LLRender::LINES, buffer_count); - if (vb) - { - buffer_list->emplace_back(vb, nullptr, LLRender::QUADS, buffer_count); - } - - gGL.vertex2f(start_x, cur_y - descender); - gGL.vertex2f(cur_x, cur_y - descender); - - vb = gGL.getBuffer(buffer_count); - if (vb) - { - buffer_list->emplace_back(vb, nullptr, LLRender::LINES, buffer_count); - } - } - else - { - gGL.begin(LLRender::LINES); - gGL.vertex2f(start_x, cur_y - descender); - gGL.vertex2f(cur_x, cur_y - descender); - gGL.end(); - } - } - else if (buffer_list) - { - vb = gGL.getBuffer(buffer_count); - if (vb) - { - buffer_list->emplace_back(vb, font_image, gGL.getMode(), buffer_count); - } + gGL.begin(LLRender::LINES); + gGL.vertex2f(start_x, cur_y - descender); + gGL.vertex2f(cur_x, cur_y - descender); + gGL.end(); } if (draw_ellipses) { - // signal a separate context - buffer_list->emplace_back(nullptr, nullptr, 0, 0); - // recursively render ellipses at end of string // we've already reserved enough room gGL.pushUIMatrix(); @@ -507,8 +416,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons S32_MAX, max_pixels, right_x, false, - use_color, - buffer_list); + use_color); gGL.popUIMatrix(); } diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 5015601cf6..de7529a583 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -33,7 +33,6 @@ #include "llimagegl.h" #include "llpointer.h" #include "llrect.h" -#include "llvertexbuffer.h" #include "v2math.h" class LLColor4; @@ -43,7 +42,6 @@ class LLFontFreetype; // Structure used to store previously requested fonts. class LLFontRegistry; -class LLVertexBuffer; class LLFontGL { @@ -81,16 +79,6 @@ public: DROP_SHADOW_SOFT }; - struct LLVertexBufferData - { - LLVertexBufferData() : mBuffer(nullptr), mImage(nullptr), mMode(0), mCount(0) {} - LLVertexBufferData(LLVertexBuffer* buffer, LLImageGL* image, U8 mode, U32 count) : mBuffer(buffer), mImage(image), mMode(mode), mCount(count) {} - LLPointer mBuffer; - LLPointer mImage; // might be a better idea to store - U8 mMode; - U32 mCount; - }; - LLFontGL(); ~LLFontGL(); @@ -131,8 +119,7 @@ public: S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX, F32* right_x=NULL, bool use_ellipses = false, - bool use_color = true, - std::list* buffer_list = nullptr) const; + bool use_color = true) const; S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const; diff --git a/indra/llrender/llfontvertexbuffer.cpp b/indra/llrender/llfontvertexbuffer.cpp index c4b68c4a6c..284762dc94 100644 --- a/indra/llrender/llfontvertexbuffer.cpp +++ b/indra/llrender/llfontvertexbuffer.cpp @@ -60,12 +60,17 @@ S32 LLFontVertexBuffer::render( bool use_ellipses, bool use_color ) { + if (!LLFontGL::sDisplayFont) //do not display texts + { + return static_cast(text.length()); + } if (mBufferList.empty()) { genBuffers(fontp, text, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color); } - else if (mLastX != x || mLastY != y + else if (mLastX != x + || mLastY != y || mLastFont != fontp || mLastColor != color // alphas change often || mLastHalign != halign @@ -74,7 +79,10 @@ S32 LLFontVertexBuffer::render( || mLastMaxChars != max_chars || mLastMaxPixels != max_pixels || mLastStyle != style - || mLastShadow != shadow) // ex: buttons change shadow state + || mLastShadow != shadow // ex: buttons change shadow state + || mLastScaleX != LLFontGL::sScaleX + || mLastScaleY != LLFontGL::sScaleY + || mLastOrigin != LLFontGL::sCurOrigin) { genBuffers(fontp, text, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color); @@ -110,8 +118,11 @@ void LLFontVertexBuffer::genBuffers( bool use_color) { mBufferList.clear(); + + gGL.beginList(&mBufferList); mChars = fontp->render(text, begin_offset, x, y, color, halign, valign, - style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color, &mBufferList); + style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color); + gGL.endList(); mLastFont = fontp; mLastOffset = begin_offset; @@ -126,67 +137,25 @@ void LLFontVertexBuffer::genBuffers( mLastStyle = style; mLastShadow = shadow; + mLastScaleX = LLFontGL::sScaleX; + mLastScaleY = LLFontGL::sScaleY; + mLastOrigin = LLFontGL::sCurOrigin; + if (right_x) { mLastRightX = *right_x; } } -void render_buffers(LLFontVertexBuffer::buffer_list_t::iterator iter, LLFontVertexBuffer::buffer_list_t::iterator end) +void LLFontVertexBuffer::renderBuffers() { + gGL.flush(); // deliberately empty pending verts gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); gGL.pushUIMatrix(); - - gGL.loadUIIdentity(); - - // Depth translation, so that floating text appears 'in-world' - // and is correctly occluded. - gGL.translatef(0.f, 0.f, LLFontGL::sCurDepth); - - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - while (iter != end) - { - if (iter->mBuffer == nullptr) - { - // elipses indicator - iter++; - break; - } - if (iter->mImage) - { - gGL.getTexUnit(0)->bind(iter->mImage); - } - else - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - iter->mBuffer->setBuffer(); - - if (LLRender::sGLCoreProfile && iter->mMode == LLRender::QUADS) - { - iter->mBuffer->drawArrays(LLRender::TRIANGLES, 0, iter->mCount); - } - else - { - iter->mBuffer->drawArrays(iter->mMode, 0, iter->mCount); - } - iter++; - } - - if (iter != end) + for (LLVertexBufferData& buffer : mBufferList) { - gGL.pushUIMatrix(); - render_buffers(iter, end); - gGL.popUIMatrix(); + buffer.draw(); } - gGL.popUIMatrix(); } -void LLFontVertexBuffer::renderBuffers() -{ - gGL.flush(); // deliberately empty pending verts - render_buffers(mBufferList.begin(), mBufferList.end()); -} - diff --git a/indra/llrender/llfontvertexbuffer.h b/indra/llrender/llfontvertexbuffer.h index 458b0a91bb..7c29e1097b 100644 --- a/indra/llrender/llfontvertexbuffer.h +++ b/indra/llrender/llfontvertexbuffer.h @@ -30,7 +30,7 @@ #include "llfontgl.h" -class LLVertexBuffer; +class LLVertexBufferData; class LLFontVertexBuffer { @@ -52,8 +52,6 @@ public: F32* right_x = NULL, bool use_ellipses = false, bool use_color = true); - - typedef std::list buffer_list_t; private: void genBuffers(const LLFontGL* fontp, @@ -71,7 +69,7 @@ private: void renderBuffers(); - buffer_list_t mBufferList; + std::list mBufferList; S32 mChars = 0; const LLFontGL *mLastFont = nullptr; S32 mLastOffset = 0; @@ -86,6 +84,12 @@ private: U8 mLastStyle = LLFontGL::NORMAL; LLFontGL::ShadowType mLastShadow = LLFontGL::NO_SHADOW; F32 mLastRightX = 0.f; + + // LLFontGL's statics + F32 mLastScaleX = 1.f; + F32 mLastScaleY = 1.f; + LLCoordGL mLastOrigin; + bool mTrackStringChanges = true; static std::hash sStringHasher; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 8cd2d9cc15..182f61f907 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -77,6 +77,7 @@ struct LLVBCache }; static std::unordered_map sVBCache; +static thread_local std::list *sBufferDataList = nullptr; static const GLenum sGLTextureType[] = { @@ -1528,6 +1529,25 @@ void LLRender::clearErrors() } } +void LLRender::beginList(std::list *list) +{ + flush(); + sBufferDataList = list; +} + +void LLRender::endList() +{ + if (sBufferDataList) + { + flush(); + sBufferDataList = nullptr; + } + else + { + llassert(false); // something failed to provide a list or closed it twice + } +} + void LLRender::begin(const GLuint& mode) { if (mode != mMode) @@ -1663,78 +1683,26 @@ void LLRender::flush() if (mBuffer) { - HBXXH64 hash; - U32 attribute_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask; + LLVertexBuffer *vb; - { - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache hash"); - - hash.update((U8*)mVerticesp.get(), count * sizeof(LLVector4a)); - if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0) - { - hash.update((U8*)mTexcoordsp.get(), count * sizeof(LLVector2)); - } - - if (attribute_mask & LLVertexBuffer::MAP_COLOR) - { - hash.update((U8*)mColorsp.get(), count * sizeof(LLColor4U)); - } - - hash.finalize(); - } - - - U64 vhash = hash.digest(); - - // check the VB cache before making a new vertex buffer - // This is a giant hack to deal with (mostly) our terrible UI rendering code - // that was built on top of OpenGL immediate mode. Huge performance wins - // can be had by not uploading geometry to VRAM unless absolutely necessary. - // Most of our usage of the "immediate mode" style draw calls is actually - // sending the same geometry over and over again. - // To leverage this, we maintain a running hash of the vertex stream being - // built up before a flush, and then check that hash against a VB - // cache just before creating a vertex buffer in VRAM - std::unordered_map::iterator cache = sVBCache.find(vhash); - - LLPointer vb; + U32 attribute_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask; - if (cache != sVBCache.end()) + if (sBufferDataList) { - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache hit"); - // cache hit, just use the cached buffer - vb = cache->second.vb; - cache->second.touched = std::chrono::steady_clock::now(); + vb = genBuffer(attribute_mask, count); + sBufferDataList->emplace_back( + vb, + mMode, + count, + gGL.getTexUnit(0)->mCurrTexture, + mMatrix[MM_MODELVIEW][mMatIdx[MM_MODELVIEW]], + mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]], + mMatrix[MM_TEXTURE0][mMatIdx[MM_TEXTURE0]] + ); } else { - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache miss"); - vb = genBuffer(attribute_mask, count); - - sVBCache[vhash] = { vb , std::chrono::steady_clock::now() }; - - static U32 miss_count = 0; - miss_count++; - if (miss_count > 1024) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache clean"); - miss_count = 0; - auto now = std::chrono::steady_clock::now(); - - using namespace std::chrono_literals; - // every 1024 misses, clean the cache of any VBs that haven't been touched in the last second - for (std::unordered_map::iterator iter = sVBCache.begin(); iter != sVBCache.end(); ) - { - if (now - iter->second.touched > 1s) - { - iter = sVBCache.erase(iter); - } - else - { - ++iter; - } - } - } + vb = bufferfromCache(attribute_mask, count); } drawBuffer(vb, mMode, count); @@ -1749,6 +1717,81 @@ void LLRender::flush() } } +LLVertexBuffer* LLRender::bufferfromCache(U32 attribute_mask, U32 count) +{ + LLVertexBuffer *vb = nullptr; + HBXXH64 hash; + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache hash"); + + hash.update((U8*)mVerticesp.get(), count * sizeof(LLVector4a)); + if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0) + { + hash.update((U8*)mTexcoordsp.get(), count * sizeof(LLVector2)); + } + + if (attribute_mask & LLVertexBuffer::MAP_COLOR) + { + hash.update((U8*)mColorsp.get(), count * sizeof(LLColor4U)); + } + + hash.finalize(); + } + + U64 vhash = hash.digest(); + + // check the VB cache before making a new vertex buffer + // This is a giant hack to deal with (mostly) our terrible UI rendering code + // that was built on top of OpenGL immediate mode. Huge performance wins + // can be had by not uploading geometry to VRAM unless absolutely necessary. + // Most of our usage of the "immediate mode" style draw calls is actually + // sending the same geometry over and over again. + // To leverage this, we maintain a running hash of the vertex stream being + // built up before a flush, and then check that hash against a VB + // cache just before creating a vertex buffer in VRAM + std::unordered_map::iterator cache = sVBCache.find(vhash); + + if (cache != sVBCache.end()) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache hit"); + // cache hit, just use the cached buffer + vb = cache->second.vb; + cache->second.touched = std::chrono::steady_clock::now(); + } + else + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache miss"); + vb = genBuffer(attribute_mask, count); + + sVBCache[vhash] = { vb , std::chrono::steady_clock::now() }; + + static U32 miss_count = 0; + miss_count++; + if (miss_count > 1024) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache clean"); + miss_count = 0; + auto now = std::chrono::steady_clock::now(); + + using namespace std::chrono_literals; + // every 1024 misses, clean the cache of any VBs that haven't been touched in the last second + for (std::unordered_map::iterator iter = sVBCache.begin(); iter != sVBCache.end(); ) + { + if (now - iter->second.touched > 1s) + { + iter = sVBCache.erase(iter); + } + else + { + ++iter; + } + } + } + } + return vb; +} + LLVertexBuffer* LLRender::genBuffer(U32 attribute_mask, S32 count) { LLVertexBuffer * vb = new LLVertexBuffer(attribute_mask); diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 5f84a4a275..aeee8685ab 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -50,7 +50,8 @@ class LLVertexBuffer; class LLCubeMap; class LLImageGL; class LLRenderTarget; -class LLTexture ; +class LLTexture; +class LLVertexBufferData; #define LL_MATRIX_STACK_DEPTH 32 @@ -415,6 +416,10 @@ public: void flush(); + // if list is set, will store buffers in list for later use, if list isn't set, will use cache + void beginList(std::list *list); + void endList(); + void begin(const GLuint& mode); void end(); @@ -491,6 +496,7 @@ public: private: friend class LLLightState; + LLVertexBuffer* bufferfromCache(U32 attribute_mask, U32 count); LLVertexBuffer* genBuffer(U32 attribute_mask, S32 count); void drawBuffer(LLVertexBuffer* vb, U32 mode, S32 count); void resetStriders(S32 count); @@ -525,7 +531,6 @@ private: std::vector mUIOffset; std::vector mUIScale; - }; extern F32 gGLModelView[16]; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 02afcf12c6..11b41730aa 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -570,6 +570,53 @@ public: static LLVBOPool* sVBOPool = nullptr; +void LLVertexBufferData::draw() +{ + if (!mVB) + { + // signal for pushUIMatrix + return; // todo: find a better way? + } + + if (mTexName) + { + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTexName); + } + else + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadMatrix(mModelView.m); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadMatrix(mProjection.m); + gGL.matrixMode(LLRender::MM_TEXTURE0); + gGL.pushMatrix(); + gGL.loadMatrix(mTexture0.m); + + mVB->setBuffer(); + + if (mMode == LLRender::QUADS && LLRender::sGLCoreProfile) + { + mVB->drawArrays(LLRender::TRIANGLES, 0, mCount); + } + else + { + mVB->drawArrays(mMode, 0, mCount); + } + + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); +} + +//============================================================================ + //static U64 LLVertexBuffer::getBytesAllocated() { diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 4ada0c335b..2a4affdc60 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -53,6 +53,37 @@ //============================================================================ // base class class LLPrivateMemoryPool; +class LLVertexBuffer; + +class LLVertexBufferData +{ +public: + LLVertexBufferData() + : mVB(nullptr) + , mMode(0) + , mCount(0) + , mTexName(0) + {} + LLVertexBufferData(LLVertexBuffer* buffer, U8 mode, U32 count, U32 tex_name, glh::matrix4f model_view, glh::matrix4f projection, glh::matrix4f texture0) + : mVB(buffer) + , mMode(mode) + , mCount(count) + , mTexName(tex_name) + , mProjection(model_view) + , mModelView(projection) + , mTexture0(texture0) + {} + void draw(); + LLPointer mVB; + U8 mMode; + U32 mCount; + U32 mTexName; + glh::matrix4f mProjection; + glh::matrix4f mModelView; + glh::matrix4f mTexture0; +}; +typedef std::list buffer_data_list_t; + class LLVertexBuffer final : public LLRefCount { public: -- cgit v1.2.3 From 57ab1a410f9cb3534bb403e034743505758579d8 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 2 Sep 2024 13:46:13 +0300 Subject: viewer#2411 A bit more coverage for font buffer --- indra/llrender/llfontgl.cpp | 3 +- indra/llrender/llfontvertexbuffer.cpp | 55 +++++++++++++++++++++++++++++++++++ indra/llrender/llfontvertexbuffer.h | 26 +++++++++++++++++ indra/llrender/llrender.cpp | 1 + indra/llrender/llvertexbuffer.cpp | 5 ++-- 5 files changed, 87 insertions(+), 3 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 7d74bb3e46..9721b020c7 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -34,7 +34,6 @@ #include "llfontbitmapcache.h" #include "llfontregistry.h" #include "llgl.h" -#include "llglslshader.h" #include "llimagegl.h" #include "llrender.h" #include "llstl.h" @@ -376,6 +375,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons cur_render_x = cur_x; cur_render_y = cur_y; } + gGL.begin(LLRender::QUADS); { gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); @@ -503,6 +503,7 @@ F32 LLFontGL::getWidthF32(const std::string& utf8text, S32 begin_offset, S32 max F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars, bool no_padding) const { + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL; F32 cur_x = 0; diff --git a/indra/llrender/llfontvertexbuffer.cpp b/indra/llrender/llfontvertexbuffer.cpp index 284762dc94..417bacd69d 100644 --- a/indra/llrender/llfontvertexbuffer.cpp +++ b/indra/llrender/llfontvertexbuffer.cpp @@ -46,6 +46,60 @@ void LLFontVertexBuffer::reset() mBufferList.clear(); } +S32 LLFontVertexBuffer::render( + const LLFontGL* fontp, + const LLWString& text, + S32 begin_offset, + LLRect rect, + const LLColor4& color, + LLFontGL::HAlign halign, LLFontGL::VAlign valign, + U8 style, + LLFontGL::ShadowType shadow, + S32 max_chars, S32 max_pixels, + F32* right_x, + bool use_ellipses, + bool use_color) +{ + LLRectf rect_float((F32)rect.mLeft, (F32)rect.mTop, (F32)rect.mRight, (F32)rect.mBottom); + return render(fontp, text, begin_offset, rect_float, color, halign, valign, style, shadow, max_chars, right_x, use_ellipses, use_color); +} + +S32 LLFontVertexBuffer::render( + const LLFontGL* fontp, + const LLWString& text, + S32 begin_offset, + LLRectf rect, + const LLColor4& color, + LLFontGL::HAlign halign, LLFontGL::VAlign valign, + U8 style, + LLFontGL::ShadowType shadow, + S32 max_chars, + F32* right_x, + bool use_ellipses, + bool use_color) +{ + F32 x = rect.mLeft; + F32 y = 0.f; + + switch (valign) + { + case LLFontGL::TOP: + y = rect.mTop; + break; + case LLFontGL::VCENTER: + y = rect.getCenterY(); + break; + case LLFontGL::BASELINE: + case LLFontGL::BOTTOM: + y = rect.mBottom; + break; + default: + y = rect.mBottom; + break; + } + return render(fontp, text, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, (S32)rect.getWidth(), right_x, use_ellipses, use_color); +} + S32 LLFontVertexBuffer::render( const LLFontGL* fontp, const LLWString& text, @@ -117,6 +171,7 @@ void LLFontVertexBuffer::genBuffers( bool use_ellipses, bool use_color) { + // todo: add a debug build assert if this triggers too often for to long? mBufferList.clear(); gGL.beginList(&mBufferList); diff --git a/indra/llrender/llfontvertexbuffer.h b/indra/llrender/llfontvertexbuffer.h index 7c29e1097b..d41c6205ac 100644 --- a/indra/llrender/llfontvertexbuffer.h +++ b/indra/llrender/llfontvertexbuffer.h @@ -40,6 +40,32 @@ public: void reset(); + S32 render(const LLFontGL* fontp, + const LLWString& text, + S32 begin_offset, + LLRect rect, + const LLColor4& color, + LLFontGL::HAlign halign = LLFontGL::LEFT, LLFontGL::VAlign valign = LLFontGL::BASELINE, + U8 style = LLFontGL::NORMAL, + LLFontGL::ShadowType shadow = LLFontGL::NO_SHADOW, + S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX, + F32* right_x = NULL, + bool use_ellipses = false, + bool use_color = true); + + S32 render(const LLFontGL* fontp, + const LLWString& text, + S32 begin_offset, + LLRectf rect, + const LLColor4& color, + LLFontGL::HAlign halign = LLFontGL::LEFT, LLFontGL::VAlign valign = LLFontGL::BASELINE, + U8 style = LLFontGL::NORMAL, + LLFontGL::ShadowType shadow = LLFontGL::NO_SHADOW, + S32 max_chars = S32_MAX, + F32* right_x = NULL, + bool use_ellipses = false, + bool use_color = true); + S32 render(const LLFontGL* fontp, const LLWString& text, S32 begin_offset, diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 182f61f907..b906563b08 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1531,6 +1531,7 @@ void LLRender::clearErrors() void LLRender::beginList(std::list *list) { + llassert(LLGLSLShader::sCurBoundShaderPtr == &gUIProgram); flush(); sBufferDataList = list; } diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 11b41730aa..156e300853 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -574,8 +574,9 @@ void LLVertexBufferData::draw() { if (!mVB) { - // signal for pushUIMatrix - return; // todo: find a better way? + llassert(false); + // Not supposed to happen, check buffer generation + return; } if (mTexName) -- cgit v1.2.3 From 4cc0edb189c4deaa205f986d20a6959aa83fb25c Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 2 Sep 2024 22:14:42 +0300 Subject: viewer#2411 Cleanup --- indra/llrender/llfontvertexbuffer.cpp | 9 +-- indra/llrender/llfontvertexbuffer.h | 7 +-- indra/llrender/llrender.cpp | 114 ---------------------------------- indra/llrender/llrender.h | 4 +- 4 files changed, 3 insertions(+), 131 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llfontvertexbuffer.cpp b/indra/llrender/llfontvertexbuffer.cpp index 417bacd69d..96ec94fe0f 100644 --- a/indra/llrender/llfontvertexbuffer.cpp +++ b/indra/llrender/llfontvertexbuffer.cpp @@ -31,8 +31,7 @@ #include "llvertexbuffer.h" -LLFontVertexBuffer::LLFontVertexBuffer(bool track_changes) -: mTrackStringChanges(track_changes) +LLFontVertexBuffer::LLFontVertexBuffer() { } @@ -141,11 +140,6 @@ S32 LLFontVertexBuffer::render( genBuffers(fontp, text, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color); } - else if (mTrackStringChanges && mLastStringHash != sStringHasher._Do_hash(text)) - { - genBuffers(fontp, text, begin_offset, x, y, color, halign, valign, - style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color); - } else { renderBuffers(); @@ -183,7 +177,6 @@ void LLFontVertexBuffer::genBuffers( mLastOffset = begin_offset; mLastMaxChars = max_chars; mLastMaxPixels = max_pixels; - mLastStringHash = sStringHasher._Do_hash(text); mLastX = x; mLastY = y; mLastColor = color; diff --git a/indra/llrender/llfontvertexbuffer.h b/indra/llrender/llfontvertexbuffer.h index d41c6205ac..67cf2ca13c 100644 --- a/indra/llrender/llfontvertexbuffer.h +++ b/indra/llrender/llfontvertexbuffer.h @@ -35,7 +35,7 @@ class LLVertexBufferData; class LLFontVertexBuffer { public: - LLFontVertexBuffer(bool track_changes = true); + LLFontVertexBuffer(); ~LLFontVertexBuffer(); void reset(); @@ -101,7 +101,6 @@ private: S32 mLastOffset = 0; S32 mLastMaxChars = 0; S32 mLastMaxPixels = 0; - size_t mLastStringHash = 0; F32 mLastX = 0.f; F32 mLastY = 0.f; LLColor4 mLastColor; @@ -115,10 +114,6 @@ private: F32 mLastScaleX = 1.f; F32 mLastScaleY = 1.f; LLCoordGL mLastOrigin; - - bool mTrackStringChanges = true; - - static std::hash sStringHasher; }; #endif diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index b906563b08..a40a668a70 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1592,50 +1592,6 @@ void LLRender::end() } } -LLVertexBuffer* LLRender::beginNoCache(const GLuint& mode, S32& count) -{ - if (mode != mMode) - { - if (mode == LLRender::QUADS) - { - mQuadCycle = 1; - } - - if (mMode == LLRender::QUADS || - mMode == LLRender::LINES || - mMode == LLRender::TRIANGLES || - mMode == LLRender::POINTS) - { - return getBuffer(count); - } - else if (mCount != 0) - { - LL_ERRS() << "gGL.begin() called redundantly." << LL_ENDL; - } - mMode = mode; - } - return nullptr; -} - -LLVertexBuffer* LLRender::endNoCache(S32& count) -{ - if (mCount == 0) - { - return nullptr; - //IMM_ERRS << "GL begin and end called with no vertices specified." << LL_ENDL; - } - - if ((mMode != LLRender::QUADS && - mMode != LLRender::LINES && - mMode != LLRender::TRIANGLES && - mMode != LLRender::POINTS) || - mCount > 2048) - { - return getBuffer(count); - } - return nullptr; -} - void LLRender::flush() { STOP_GLERROR; @@ -1844,76 +1800,6 @@ void LLRender::resetStriders(S32 count) mCount = 0; } -LLVertexBuffer* LLRender::getBuffer(S32 & count) -{ - STOP_GLERROR; - LLVertexBuffer *vb; - if (mCount > 0) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - llassert(LLGLSLShader::sCurBoundShaderPtr != nullptr); - if (!mUIOffset.empty()) - { - sUICalls++; - sUIVerts += mCount; - } - - //store mCount in a local variable to avoid re-entrance (drawArrays may call flush) - count = mCount; - - if (mMode == LLRender::QUADS && !sGLCoreProfile) - { - if (mCount % 4 != 0) - { - count -= (mCount % 4); - LL_WARNS() << "Incomplete quad requested." << LL_ENDL; - } - } - - if (mMode == LLRender::TRIANGLES) - { - if (mCount % 3 != 0) - { - count -= (mCount % 3); - LL_WARNS() << "Incomplete triangle requested." << LL_ENDL; - } - } - - if (mMode == LLRender::LINES) - { - if (mCount % 2 != 0) - { - count -= (mCount % 2); - LL_WARNS() << "Incomplete line requested." << LL_ENDL; - } - } - - mCount = 0; - - if (mBuffer) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache miss"); - - U32 attribute_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask; - vb = genBuffer(attribute_mask, count); - drawBuffer(vb, mMode, count); - } - else - { - // mBuffer is present in main thread and not present in an image thread - LL_ERRS() << "A flush call from outside main rendering thread" << LL_ENDL; - } - - resetStriders(count); - } - else - { - count = 0; - } - - return vb; -} - void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) { //the range of mVerticesp, mColorsp and mTexcoordsp is [0, 4095] diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index aeee8685ab..39c13e328a 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -45,6 +45,7 @@ #include "glh/glh_linear.h" #include +#include class LLVertexBuffer; class LLCubeMap; @@ -423,9 +424,6 @@ public: void begin(const GLuint& mode); void end(); - LLVertexBuffer* beginNoCache(const GLuint& mode, S32& count); - LLVertexBuffer* endNoCache(S32& count); - LLVertexBuffer* getBuffer(S32& count); U8 getMode() const { return mMode; } void vertex2i(const GLint& x, const GLint& y); -- cgit v1.2.3 From 2fc8d5ff3cfa1b9ad00b310cd4a6cdb557b9415c Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 3 Sep 2024 17:22:04 +0300 Subject: viewer#2411 Cleanup #2 --- indra/llrender/llrender.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index a40a668a70..828a509971 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1531,6 +1531,10 @@ void LLRender::clearErrors() void LLRender::beginList(std::list *list) { + if (sBufferDataList) + { + LL_ERRS() << "beginList called while another list is open." << LL_ENDL; + } llassert(LLGLSLShader::sCurBoundShaderPtr == &gUIProgram); flush(); sBufferDataList = list; @@ -1545,7 +1549,7 @@ void LLRender::endList() } else { - llassert(false); // something failed to provide a list or closed it twice + llassert(false); // endList called without an open list } } -- cgit v1.2.3 From cb9f3dcfe9a55789b757bf5a7d9af3d93710c20f Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 4 Sep 2024 11:34:44 -0500 Subject: #2482 Low end NVIDIA compatibility pass (#2486) - Use GL_NVX_gpu_memory_info when available - Disable transparent water on Mid+ and lower - Adjust GPU benchmark to better tell the truth - Texture bias tune up - viewer-private/#277 - Report foreground_time in viewer stats --- indra/llrender/llgl.cpp | 12 ++++++++++++ indra/llrender/llgl.h | 1 + 2 files changed, 13 insertions(+) (limited to 'indra/llrender') diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 7959b3bb57..0afe78a30c 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -1038,6 +1038,7 @@ void LLGLManager::initWGL() GLH_EXT_NAME(wglGetGPUIDsAMD) = (PFNWGLGETGPUIDSAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUIDsAMD"); GLH_EXT_NAME(wglGetGPUInfoAMD) = (PFNWGLGETGPUINFOAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUInfoAMD"); } + mHasNVXGpuMemoryInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts); if (ExtensionExists("WGL_EXT_swap_control", gGLHExts.mSysExts)) { @@ -1205,6 +1206,17 @@ bool LLGLManager::initGL() LL_WARNS("RenderInit") << "VRAM Detected (AMDAssociations):" << mVRAM << LL_ENDL; } } + else if (mHasNVXGpuMemoryInfo) + { + GLint mem_kb = 0; + glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &mem_kb); + mVRAM = mem_kb / 1024; + + if (mVRAM != 0) + { + LL_WARNS("RenderInit") << "VRAM Detected (NVXGpuMemoryInfo):" << mVRAM << LL_ENDL; + } + } #endif #if LL_WINDOWS diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index be1c0a532a..cd1ba55b16 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -97,6 +97,7 @@ public: // Vendor-specific extensions bool mHasAMDAssociations = false; + bool mHasNVXGpuMemoryInfo = false; bool mIsAMD; bool mIsNVIDIA; -- cgit v1.2.3 From 238a2a64b31e6a0b431309e363067a7fe57125ae Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 4 Sep 2024 13:42:11 +0300 Subject: viewer#2411 Use font buffer in text segments --- indra/llrender/llfontvertexbuffer.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/llrender') diff --git a/indra/llrender/llfontvertexbuffer.cpp b/indra/llrender/llfontvertexbuffer.cpp index 96ec94fe0f..392f235aad 100644 --- a/indra/llrender/llfontvertexbuffer.cpp +++ b/indra/llrender/llfontvertexbuffer.cpp @@ -42,6 +42,8 @@ LLFontVertexBuffer::~LLFontVertexBuffer() void LLFontVertexBuffer::reset() { + // Todo: some form of debug only frequecy check&assert to see if this is happening too often. + // Regenerating this list is expensive mBufferList.clear(); } -- cgit v1.2.3