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/llfontvertexbuffer.cpp | 157 ++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 indra/llrender/llfontvertexbuffer.cpp (limited to 'indra/llrender/llfontvertexbuffer.cpp') 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; + } +} + -- 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/llfontvertexbuffer.cpp | 119 ++++++++++++++++++++++------------ 1 file changed, 77 insertions(+), 42 deletions(-) (limited to 'indra/llrender/llfontvertexbuffer.cpp') 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()); +} + -- 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/llfontvertexbuffer.cpp | 75 ++++++++++------------------------- 1 file changed, 22 insertions(+), 53 deletions(-) (limited to 'indra/llrender/llfontvertexbuffer.cpp') 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()); -} - -- 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/llfontvertexbuffer.cpp | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'indra/llrender/llfontvertexbuffer.cpp') 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); -- 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 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'indra/llrender/llfontvertexbuffer.cpp') 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; -- 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/llfontvertexbuffer.cpp') 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 From 440c7b20dab3aa09c04bf3e72b4997181e585cbb Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 26 Sep 2024 18:09:32 +0300 Subject: #2411 Allow disabling and enabling LLFontVertexBuffer for testing purposes --- indra/llrender/llfontvertexbuffer.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'indra/llrender/llfontvertexbuffer.cpp') diff --git a/indra/llrender/llfontvertexbuffer.cpp b/indra/llrender/llfontvertexbuffer.cpp index 392f235aad..f5d6b03cd6 100644 --- a/indra/llrender/llfontvertexbuffer.cpp +++ b/indra/llrender/llfontvertexbuffer.cpp @@ -31,6 +31,8 @@ #include "llvertexbuffer.h" +bool LLFontVertexBuffer::sEnableBufferCollection = true; + LLFontVertexBuffer::LLFontVertexBuffer() { } @@ -119,6 +121,11 @@ S32 LLFontVertexBuffer::render( { return static_cast(text.length()); } + if (!sEnableBufferCollection) + { + // For debug purposes and performance testing + return fontp->render(text, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color); + } if (mBufferList.empty()) { genBuffers(fontp, text, begin_offset, x, y, color, halign, valign, -- cgit v1.2.3