diff options
| author | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2024-08-28 23:05:58 +0300 | 
|---|---|---|
| committer | Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> | 2024-09-04 10:16:46 +0300 | 
| commit | 4ae1de1f8a78d795958d67afab8356f9a13f707d (patch) | |
| tree | ea0fe05983562f061a4748a6f4af7253018f9660 /indra/llrender | |
| parent | 36423bd6603c5708028c6e8e9705587b961a4bb2 (diff) | |
viewer#2411 LLFontGL::render optimizations
Diffstat (limited to 'indra/llrender')
| -rw-r--r-- | indra/llrender/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/llrender/llfontgl.cpp | 124 | ||||
| -rw-r--r-- | indra/llrender/llfontgl.h | 15 | ||||
| -rw-r--r-- | indra/llrender/llfontvertexbuffer.cpp | 157 | ||||
| -rw-r--r-- | indra/llrender/llfontvertexbuffer.h | 85 | ||||
| -rw-r--r-- | indra/llrender/llrender.cpp | 197 | ||||
| -rw-r--r-- | indra/llrender/llrender.h | 10 | 
7 files changed, 538 insertions, 52 deletions
| 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 <boost/tokenizer.hpp> @@ -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<LLVertexBufferData> *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<EFontGlyphType, S32> 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<LLVertexBuffer> mBuffer; +        LLPointer <LLImageGL> 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<LLVertexBufferData>* 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<LLFontGL::LLVertexBufferData> 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<LLWString> 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]; | 
