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 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 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 From cde5d29faf84c5cb7fc1b0d0ff6d03f3b7354c8f Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Tue, 10 Sep 2024 18:27:45 -0500 Subject: Profile guided optimizations --- indra/llrender/llimagegl.cpp | 52 ++++++++++++++++++++++++++++------ indra/llrender/llvertexbuffer.cpp | 59 +++++++++++++++++++++++++++++++++++++-- indra/llrender/llvertexbuffer.h | 12 ++++++++ 3 files changed, 112 insertions(+), 11 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 68c20048ec..67b4ada62f 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1045,15 +1045,47 @@ void sub_image_lines(U32 target, S32 miplevel, S32 x_offset, S32 y_offset, S32 w { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + LL_PROFILE_ZONE_NUM(width); + LL_PROFILE_ZONE_NUM(height); + U32 components = LLImageGL::dataFormatComponents(pixformat); U32 type_width = type_width_from_pixtype(pixtype); const U32 line_width = data_width * components * type_width; const U32 y_offset_end = y_offset + height; - for (U32 y_pos = y_offset; y_pos < y_offset_end; ++y_pos) + + if (width == data_width && height % 32 == 0) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("subimage - batched lines"); + + // full width, batch multiple lines at a time + // set batch size based on width + U32 batch_size = 32; + + if (width > 1024) + { + batch_size = 8; + } + else if (width > 512) + { + batch_size = 16; + } + + // full width texture, do 32 lines at a time + for (U32 y_pos = y_offset; y_pos < y_offset_end; y_pos += batch_size) + { + glTexSubImage2D(target, miplevel, x_offset, y_pos, width, batch_size, pixformat, pixtype, src); + src += line_width * batch_size; + } + } + else { - glTexSubImage2D(target, miplevel, x_offset, y_pos, width, 1, pixformat, pixtype, src); - src += line_width; + // partial width or strange height + for (U32 y_pos = y_offset; y_pos < y_offset_end; y_pos += 1) + { + glTexSubImage2D(target, miplevel, x_offset, y_pos, width, 1, pixformat, pixtype, src); + src += line_width; + } } } @@ -2139,6 +2171,8 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) return ; } + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + U32 length = w * h; U32 alphatotal = 0; @@ -2150,15 +2184,15 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) // this will mid-skew the data (and thus increase the chances of not // being used as a mask) from high-frequency alpha maps which // suffer the worst from aliasing when used as alpha masks. - if (w >= 2 && h >= 2) + if (w >= 4 && h >= 4) { - llassert(w%2 == 0); - llassert(h%2 == 0); + llassert(w%4 == 0); + llassert(h%4 == 0); const GLubyte* rowstart = ((const GLubyte*) data_in) + mAlphaOffset; - for (U32 y = 0; y < h; y+=2) + for (U32 y = 0; y < h; y+=4) { const GLubyte* current = rowstart; - for (U32 x = 0; x < w; x+=2) + for (U32 x = 0; x < w; x+=4) { const U32 s1 = current[0]; alphatotal += s1; @@ -2182,7 +2216,7 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) } - rowstart += 2 * w * mAlphaStride; + rowstart += 4 * w * mAlphaStride; } length *= 2; // we sampled everything twice, essentially } diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 156e300853..c1f239fc43 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -954,6 +954,25 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask) } } +// list of mapped buffers +// NOTE: must not be LLPointer to avoid breaking non-ref-counted LLVertexBuffer instances +static std::vector sMappedBuffers; + +//static +void LLVertexBuffer::flushBuffers() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; + // must only be called from main thread + llassert(LLCoros::on_main_thread_main_coro()); + for (auto& buffer : sMappedBuffers) + { + buffer->_unmapBuffer(); + buffer->mMapped = false; + } + + sMappedBuffers.resize(0); +} + //static U32 LLVertexBuffer::calcOffsets(const U32& typemask, U32* offsets, U32 num_vertices) { @@ -997,6 +1016,12 @@ U32 LLVertexBuffer::calcVertexSize(const U32& typemask) //virtual LLVertexBuffer::~LLVertexBuffer() { + if (mMapped) + { // is on the mapped buffer list but doesn't need to be flushed + mMapped = false; + unmapBuffer(); + } + destroyGLBuffer(); destroyGLIndices(); @@ -1198,6 +1223,7 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, U32 start, U32 end) U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 index, S32 count) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; + _mapBuffer(); if (count == -1) { @@ -1233,6 +1259,7 @@ U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 inde U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; + _mapBuffer(); if (count == -1) { @@ -1289,11 +1316,11 @@ void LLVertexBuffer::flush_vbo(GLenum target, U32 start, U32 end, void* data, U8 LL_PROFILE_ZONE_NUM(end); LL_PROFILE_ZONE_NUM(end-start); - constexpr U32 block_size = 8192; + constexpr U32 block_size = 65536; for (U32 i = start; i <= end; i += block_size) { - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("glBufferSubData block"); + //LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("glBufferSubData block"); //LL_PROFILE_GPU_ZONE("glBufferSubData"); U32 tend = llmin(i + block_size, end); U32 size = tend - i + 1; @@ -1304,8 +1331,29 @@ void LLVertexBuffer::flush_vbo(GLenum target, U32 start, U32 end, void* data, U8 } void LLVertexBuffer::unmapBuffer() +{ + flushBuffers(); +} + +void LLVertexBuffer::_mapBuffer() +{ + // must only be called from main thread + llassert(LLCoros::on_main_thread_main_coro()); + if (!mMapped) + { + mMapped = true; + sMappedBuffers.push_back(this); + } +} + +void LLVertexBuffer::_unmapBuffer() { STOP_GLERROR; + if (!mMapped) + { + return; + } + struct SortMappedRegion { bool operator()(const MappedRegion& lhs, const MappedRegion& rhs) @@ -1549,6 +1597,13 @@ void LLVertexBuffer::setBuffer() return; } #endif + + if (mMapped) + { + LL_WARNS() << "Missing call to unmapBuffer or flushBuffers" << LL_ENDL; + _unmapBuffer(); + } + // no data may be pending llassert(mMappedVertexRegions.empty()); llassert(mMappedIndexRegions.empty()); diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 2a4affdc60..9fe468f89e 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -120,6 +120,9 @@ public: // indexed by the following enum static U32 calcOffsets(const U32& typemask, U32* offsets, U32 num_vertices); + // flush any pending mapped buffers + static void flushBuffers(); + //WARNING -- when updating these enums you MUST // 1 - update LLVertexBuffer::sTypeSize // 2 - update LLVertexBuffer::vb_type_name @@ -190,6 +193,8 @@ public: // map for data access (see also getFooStrider below) U8* mapVertexBuffer(AttributeType type, U32 index, S32 count = -1); U8* mapIndexBuffer(U32 index, S32 count = -1); + + // synonym for flushBuffers void unmapBuffer(); // set for rendering @@ -312,6 +317,13 @@ private: bool allocateBuffer(S32 nverts, S32 nindices, bool create) { return allocateBuffer(nverts, nindices); } + // actually unmap buffer + void _unmapBuffer(); + + // add to set of mapped buffers + void _mapBuffer(); + bool mMapped = false; + public: static U64 getBytesAllocated(); -- cgit v1.2.3 From 264c57831bc6ca9be1c465c10a2558c3d28b936e Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Thu, 12 Sep 2024 09:00:58 -0700 Subject: Fix warning spam from missing call to unmapBuffer introduced in #2544 (#2556) --- indra/llrender/llvertexbuffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index c1f239fc43..666d792d1d 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -1600,7 +1600,7 @@ void LLVertexBuffer::setBuffer() if (mMapped) { - LL_WARNS() << "Missing call to unmapBuffer or flushBuffers" << LL_ENDL; + LL_WARNS_ONCE() << "Missing call to unmapBuffer or flushBuffers" << LL_ENDL; _unmapBuffer(); } -- cgit v1.2.3 From 14a3c7573652e669c35dd331214f572da985c2a9 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 12 Sep 2024 11:05:14 -0500 Subject: Mac compatibility pass. --- indra/llrender/llvertexbuffer.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index c1f239fc43..de727eec7b 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -1301,6 +1301,9 @@ U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count) void LLVertexBuffer::flush_vbo(GLenum target, U32 start, U32 end, void* data, U8* dst) { #if LL_DARWIN + // on OS X, flush_vbo doesn't actually write to the GL buffer, so be sure to call + // _mapBuffer to tag the buffer for flushing to GL + _mapBuffer(); LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb memcpy"); STOP_GLERROR; // copy into mapped buffer @@ -1591,12 +1594,6 @@ bool LLVertexBuffer::getClothWeightStrider(LLStrider& strider, U32 in void LLVertexBuffer::setBuffer() { STOP_GLERROR; -#if LL_DARWIN - if (!mGLBuffer) - { // OS X doesn't allocate a buffer until we call unmapBuffer - return; - } -#endif if (mMapped) { -- cgit v1.2.3 From b713f56d07cffb21cad5928bf30d6d4b6dc79de9 Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Thu, 12 Sep 2024 09:22:10 -0700 Subject: Replace glh_linear usage with GLM (#2554) --- indra/llrender/llgl.cpp | 43 ++++---- indra/llrender/llgl.h | 12 +-- indra/llrender/llrender.cpp | 216 +++++++++++++++++--------------------- indra/llrender/llrender.h | 35 +++--- indra/llrender/llvertexbuffer.cpp | 7 +- indra/llrender/llvertexbuffer.h | 12 ++- 6 files changed, 155 insertions(+), 170 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 0db1e27b01..c62cacdce6 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -50,6 +50,10 @@ #include "llglheaders.h" #include "llglslshader.h" +#include "glm/glm.hpp" +#include +#include "glm/gtc/type_ptr.hpp" + #if LL_WINDOWS #include "lldxhardware.h" #endif @@ -2694,7 +2698,7 @@ void parse_glsl_version(S32& major, S32& minor) LLStringUtil::convertToS32(minor_str, minor); } -LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glh::matrix4f& modelview, const glh::matrix4f& projection, bool apply) +LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glm::mat4& modelview, const glm::mat4& projection, bool apply) { mApply = apply; @@ -2721,13 +2725,12 @@ void LLGLUserClipPlane::disable() void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d) { - glh::matrix4f& P = mProjection; - glh::matrix4f& M = mModelview; + const glm::mat4& P = mProjection; + const glm::mat4& M = mModelview; - glh::matrix4f invtrans_MVP = (P * M).inverse().transpose(); - glh::vec4f oplane(a,b,c,d); - glh::vec4f cplane; - invtrans_MVP.mult_matrix_vec(oplane, cplane); + glm::mat4 invtrans_MVP = glm::transpose(glm::inverse(P*M)); + glm::vec4 oplane(a,b,c,d); + glm::vec4 cplane = invtrans_MVP * oplane; cplane /= fabs(cplane[2]); // normalize such that depth is not scaled cplane[3] -= 1; @@ -2735,13 +2738,13 @@ void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d) if(cplane[2] < 0) cplane *= -1; - glh::matrix4f suffix; - suffix.set_row(2, cplane); - glh::matrix4f newP = suffix * P; + glm::mat4 suffix; + suffix = glm::row(suffix, 2, cplane); + glm::mat4 newP = suffix * P; gGL.matrixMode(LLRender::MM_PROJECTION); gGL.pushMatrix(); - gGL.loadMatrix(newP.m); - gGLObliqueProjectionInverse = LLMatrix4(newP.inverse().transpose().m); + gGL.loadMatrix(glm::value_ptr(newP)); + gGLObliqueProjectionInverse = LLMatrix4(glm::value_ptr(glm::transpose(glm::inverse(newP)))); gGL.matrixMode(LLRender::MM_MODELVIEW); } @@ -2838,31 +2841,27 @@ void LLGLDepthTest::checkState() LLGLSquashToFarClip::LLGLSquashToFarClip() { - glh::matrix4f proj = get_current_projection(); + glm::mat4 proj = get_current_projection(); setProjectionMatrix(proj, 0); } -LLGLSquashToFarClip::LLGLSquashToFarClip(glh::matrix4f& P, U32 layer) +LLGLSquashToFarClip::LLGLSquashToFarClip(const glm::mat4& P, U32 layer) { setProjectionMatrix(P, layer); } - -void LLGLSquashToFarClip::setProjectionMatrix(glh::matrix4f& projection, U32 layer) +void LLGLSquashToFarClip::setProjectionMatrix(glm::mat4 projection, U32 layer) { - F32 depth = 0.99999f - 0.0001f * layer; - for (U32 i = 0; i < 4; i++) - { - projection.element(2, i) = projection.element(3, i) * depth; - } + glm::vec4 P_row_3 = glm::row(projection, 3) * depth; + projection = glm::row(projection, 2, P_row_3); LLRender::eMatrixMode last_matrix_mode = gGL.getMatrixMode(); gGL.matrixMode(LLRender::MM_PROJECTION); gGL.pushMatrix(); - gGL.loadMatrix(projection.m); + gGL.loadMatrix(glm::value_ptr(projection)); gGL.matrixMode(last_matrix_mode); } diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index cd1ba55b16..17f825bd71 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -43,7 +43,7 @@ #include "llinstancetracker.h" #include "llglheaders.h" -#include "glh/glh_linear.h" +#include "glm/mat4x4.hpp" extern bool gDebugGL; extern bool gDebugSession; @@ -317,7 +317,7 @@ class LLGLUserClipPlane { public: - LLGLUserClipPlane(const LLPlane& plane, const glh::matrix4f& modelview, const glh::matrix4f& projection, bool apply = true); + LLGLUserClipPlane(const LLPlane& plane, const glm::mat4& modelview, const glm::mat4& projection, bool apply = true); ~LLGLUserClipPlane(); void setPlane(F32 a, F32 b, F32 c, F32 d); @@ -326,8 +326,8 @@ public: private: bool mApply; - glh::matrix4f mProjection; - glh::matrix4f mModelview; + glm::mat4 mProjection; + glm::mat4 mModelview; }; /* @@ -341,9 +341,9 @@ class LLGLSquashToFarClip { public: LLGLSquashToFarClip(); - LLGLSquashToFarClip(glh::matrix4f& projection, U32 layer = 0); + LLGLSquashToFarClip(const glm::mat4& projection, U32 layer = 0); - void setProjectionMatrix(glh::matrix4f& projection, U32 layer); + void setProjectionMatrix(glm::mat4 projection, U32 layer); ~LLGLSquashToFarClip(); }; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 828a509971..16a8309a9a 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -36,6 +36,7 @@ #include "lltexture.h" #include "llshadermgr.h" #include "hbxxh.h" +#include "glm/gtc/type_ptr.hpp" #if LL_WINDOWS extern void APIENTRY gl_debug_callback(GLenum source, @@ -57,8 +58,8 @@ F32 gGLLastProjection[16]; F32 gGLProjection[16]; // transform from last frame's camera space to this frame's camera space (and inverse) -F32 gGLDeltaModelView[16]; -F32 gGLInverseDeltaModelView[16]; +glm::mat4 gGLDeltaModelView; +glm::mat4 gGLInverseDeltaModelView; S32 gGLViewport[4]; @@ -735,10 +736,10 @@ void LLLightState::setPosition(const LLVector4& position) ++gGL.mLightHash; mPosition = position; //transform position by current modelview matrix - glh::vec4f pos(position.mV); - const glh::matrix4f& mat = gGL.getModelviewMatrix(); - mat.mult_matrix_vec(pos); - mPosition.set(pos.v); + glm::vec4 pos(glm::make_vec4(position.mV)); + const glm::mat4& mat = gGL.getModelviewMatrix(); + pos = mat * pos; + mPosition.set(glm::value_ptr(pos)); } void LLLightState::setConstantAttenuation(const F32& atten) @@ -790,13 +791,13 @@ void LLLightState::setSpotDirection(const LLVector3& direction) { //always set direction because modelview matrix may have changed ++gGL.mLightHash; - mSpotDirection = direction; + //transform direction by current modelview matrix - glh::vec3f dir(direction.mV); - const glh::matrix4f& mat = gGL.getModelviewMatrix(); - mat.mult_matrix_dir(dir); + glm::vec3 dir(glm::make_vec3(direction.mV)); + const glm::mat3 mat(gGL.getModelviewMatrix()); + dir = mat * dir; - mSpotDirection.set(dir.v); + mSpotDirection.set(glm::value_ptr(dir)); } LLRender::LLRender() @@ -830,6 +831,10 @@ LLRender::LLRender() for (U32 i = 0; i < NUM_MATRIX_MODES; ++i) { + for (U32 j = 0; j < LL_MATRIX_STACK_DEPTH; ++j) + { + mMatrix[i][j] = glm::identity(); + } mMatIdx[i] = 0; mMatHash[i] = 0; mCurMatHash[i] = 0xFFFFFFFF; @@ -991,12 +996,12 @@ void LLRender::syncMatrices() LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - static glh::matrix4f cached_mvp; - static glh::matrix4f cached_inv_mdv; + static glm::mat4 cached_mvp; + static glm::mat4 cached_inv_mdv; static U32 cached_mvp_mdv_hash = 0xFFFFFFFF; static U32 cached_mvp_proj_hash = 0xFFFFFFFF; - static glh::matrix4f cached_normal; + static glm::mat4 cached_normal; static U32 cached_normal_hash = 0xFFFFFFFF; if (shader) @@ -1006,15 +1011,15 @@ void LLRender::syncMatrices() U32 i = MM_MODELVIEW; if (mMatHash[MM_MODELVIEW] != shader->mMatHash[MM_MODELVIEW]) { //update modelview, normal, and MVP - glh::matrix4f& mat = mMatrix[MM_MODELVIEW][mMatIdx[MM_MODELVIEW]]; + const glm::mat4& mat = mMatrix[MM_MODELVIEW][mMatIdx[MM_MODELVIEW]]; // if MDV has changed, update the cached inverse as well if (cached_mvp_mdv_hash != mMatHash[MM_MODELVIEW]) { - cached_inv_mdv = mat.inverse(); + cached_inv_mdv = glm::inverse(mat); } - shader->uniformMatrix4fv(name[MM_MODELVIEW], 1, GL_FALSE, mat.m); + shader->uniformMatrix4fv(name[MM_MODELVIEW], 1, GL_FALSE, glm::value_ptr(mat)); shader->mMatHash[MM_MODELVIEW] = mMatHash[MM_MODELVIEW]; //update normal matrix @@ -1023,17 +1028,17 @@ void LLRender::syncMatrices() { if (cached_normal_hash != mMatHash[i]) { - cached_normal = cached_inv_mdv.transpose(); + cached_normal = glm::transpose(cached_inv_mdv); cached_normal_hash = mMatHash[i]; } - glh::matrix4f& norm = cached_normal; + auto norm = glm::value_ptr(cached_normal); F32 norm_mat[] = { - norm.m[0], norm.m[1], norm.m[2], - norm.m[4], norm.m[5], norm.m[6], - norm.m[8], norm.m[9], norm.m[10] + norm[0], norm[1], norm[2], + norm[4], norm[5], norm[6], + norm[8], norm[9], norm[10] }; shader->uniformMatrix3fv(LLShaderMgr::NORMAL_MATRIX, 1, GL_FALSE, norm_mat); @@ -1041,7 +1046,7 @@ void LLRender::syncMatrices() if (shader->getUniformLocation(LLShaderMgr::INVERSE_MODELVIEW_MATRIX)) { - shader->uniformMatrix4fv(LLShaderMgr::INVERSE_MODELVIEW_MATRIX, 1, GL_FALSE, cached_inv_mdv.m); + shader->uniformMatrix4fv(LLShaderMgr::INVERSE_MODELVIEW_MATRIX, 1, GL_FALSE, glm::value_ptr(cached_inv_mdv)); } //update MVP matrix @@ -1054,36 +1059,36 @@ void LLRender::syncMatrices() if (cached_mvp_mdv_hash != mMatHash[i] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION]) { cached_mvp = mat; - cached_mvp.mult_left(mMatrix[proj][mMatIdx[proj]]); + cached_mvp = mMatrix[proj][mMatIdx[proj]] * cached_mvp; cached_mvp_mdv_hash = mMatHash[i]; cached_mvp_proj_hash = mMatHash[MM_PROJECTION]; } - shader->uniformMatrix4fv(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX, 1, GL_FALSE, cached_mvp.m); + shader->uniformMatrix4fv(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX, 1, GL_FALSE, glm::value_ptr(cached_mvp)); } } i = MM_PROJECTION; if (mMatHash[MM_PROJECTION] != shader->mMatHash[MM_PROJECTION]) { //update projection matrix, normal, and MVP - glh::matrix4f& mat = mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]]; + const glm::mat4& mat = mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]]; // GZ: This was previously disabled seemingly due to a bug involving the deferred renderer's regular pushing and popping of mats. // We're reenabling this and cleaning up the code around that - that would've been the appropriate course initially. // Anything beyond the standard proj and inv proj mats are special cases. Please setup special uniforms accordingly in the future. if (shader->getUniformLocation(LLShaderMgr::INVERSE_PROJECTION_MATRIX)) { - glh::matrix4f inv_proj = mat.inverse(); - shader->uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, false, inv_proj.m); + glm::mat4 inv_proj = glm::inverse(mat); + shader->uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, false, glm::value_ptr(inv_proj)); } // Used by some full screen effects - such as full screen lights, glow, etc. if (shader->getUniformLocation(LLShaderMgr::IDENTITY_MATRIX)) { - shader->uniformMatrix4fv(LLShaderMgr::IDENTITY_MATRIX, 1, GL_FALSE, glh::matrix4f::identity().m); + shader->uniformMatrix4fv(LLShaderMgr::IDENTITY_MATRIX, 1, GL_FALSE, glm::value_ptr(glm::identity())); } - shader->uniformMatrix4fv(name[MM_PROJECTION], 1, GL_FALSE, mat.m); + shader->uniformMatrix4fv(name[MM_PROJECTION], 1, GL_FALSE, glm::value_ptr(mat)); shader->mMatHash[MM_PROJECTION] = mMatHash[MM_PROJECTION]; if (!mvp_done) @@ -1096,12 +1101,12 @@ void LLRender::syncMatrices() { U32 mdv = MM_MODELVIEW; cached_mvp = mat; - cached_mvp.mult_right(mMatrix[mdv][mMatIdx[mdv]]); + cached_mvp *= mMatrix[mdv][mMatIdx[mdv]]; cached_mvp_mdv_hash = mMatHash[MM_MODELVIEW]; cached_mvp_proj_hash = mMatHash[MM_PROJECTION]; } - shader->uniformMatrix4fv(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX, 1, GL_FALSE, cached_mvp.m); + shader->uniformMatrix4fv(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX, 1, GL_FALSE, glm::value_ptr(cached_mvp)); } } } @@ -1110,7 +1115,7 @@ void LLRender::syncMatrices() { if (mMatHash[i] != shader->mMatHash[i]) { - shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mMatrix[i][mMatIdx[i]].m); + shader->uniformMatrix4fv(name[i], 1, GL_FALSE, glm::value_ptr(mMatrix[i][mMatIdx[i]])); shader->mMatHash[i] = mMatHash[i]; } } @@ -1129,12 +1134,7 @@ void LLRender::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z) flush(); { - glh::matrix4f trans_mat(1,0,0,x, - 0,1,0,y, - 0,0,1,z, - 0,0,0,1); - - mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(trans_mat); + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] = glm::translate(mMatrix[mMatrixMode][mMatIdx[mMatrixMode]], glm::vec3(x, y, z)); mMatHash[mMatrixMode]++; } } @@ -1144,12 +1144,7 @@ void LLRender::scalef(const GLfloat& x, const GLfloat& y, const GLfloat& z) flush(); { - glh::matrix4f scale_mat(x,0,0,0, - 0,y,0,0, - 0,0,z,0, - 0,0,0,1); - - mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(scale_mat); + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] = glm::scale(mMatrix[mMatrixMode][mMatIdx[mMatrixMode]], glm::vec3(x, y, z)); mMatHash[mMatrixMode]++; } } @@ -1159,13 +1154,7 @@ void LLRender::ortho(F32 left, F32 right, F32 bottom, F32 top, F32 zNear, F32 zF flush(); { - - glh::matrix4f ortho_mat(2.f/(right-left),0,0, -(right+left)/(right-left), - 0,2.f/(top-bottom),0, -(top+bottom)/(top-bottom), - 0,0,-2.f/(zFar-zNear), -(zFar+zNear)/(zFar-zNear), - 0,0,0,1); - - mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(ortho_mat); + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] *= glm::ortho(left, right, bottom, top, zNear, zFar); mMatHash[mMatrixMode]++; } } @@ -1175,19 +1164,7 @@ void LLRender::rotatef(const GLfloat& a, const GLfloat& x, const GLfloat& y, con flush(); { - F32 r = a * DEG_TO_RAD; - - F32 c = cosf(r); - F32 s = sinf(r); - - F32 ic = 1.f-c; - - glh::matrix4f rot_mat(x*x*ic+c, x*y*ic-z*s, x*z*ic+y*s, 0, - x*y*ic+z*s, y*y*ic+c, y*z*ic-x*s, 0, - x*z*ic-y*s, y*z*ic+x*s, z*z*ic+c, 0, - 0,0,0,1); - - mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(rot_mat); + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] = glm::rotate(mMatrix[mMatrixMode][mMatIdx[mMatrixMode]], glm::radians(a), glm::vec3(x,y,z)); mMatHash[mMatrixMode]++; } } @@ -1229,7 +1206,7 @@ void LLRender::loadMatrix(const GLfloat* m) { flush(); { - mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].set_value((GLfloat*) m); + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] = glm::make_mat4((GLfloat*) m); mMatHash[mMatrixMode]++; } } @@ -1238,9 +1215,7 @@ void LLRender::multMatrix(const GLfloat* m) { flush(); { - glh::matrix4f mat((GLfloat*) m); - - mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(mat); + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] *= glm::make_mat4(m); mMatHash[mMatrixMode]++; } } @@ -1283,17 +1258,17 @@ void LLRender::loadIdentity() { llassert_always(mMatrixMode < NUM_MATRIX_MODES) ; - mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].make_identity(); + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] = glm::identity(); mMatHash[mMatrixMode]++; } } -const glh::matrix4f& LLRender::getModelviewMatrix() +const glm::mat4& LLRender::getModelviewMatrix() { return mMatrix[MM_MODELVIEW][mMatIdx[MM_MODELVIEW]]; } -const glh::matrix4f& LLRender::getProjectionMatrix() +const glm::mat4& LLRender::getProjectionMatrix() { return mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]]; } @@ -2214,85 +2189,90 @@ void LLRender::debugTexUnits(void) LL_INFOS("TextureUnit") << "Active TexUnit Enabled : " << active_enabled << LL_ENDL; } - - -glh::matrix4f copy_matrix(F32* src) -{ - glh::matrix4f ret; - ret.set_value(src); - return ret; -} - -glh::matrix4f get_current_modelview() +glm::mat4 get_current_modelview() { - return copy_matrix(gGLModelView); + return glm::make_mat4(gGLModelView); } -glh::matrix4f get_current_projection() +glm::mat4 get_current_projection() { - return copy_matrix(gGLProjection); + return glm::make_mat4(gGLProjection); } -glh::matrix4f get_last_modelview() +glm::mat4 get_last_modelview() { - return copy_matrix(gGLLastModelView); + return glm::make_mat4(gGLLastModelView); } -glh::matrix4f get_last_projection() +glm::mat4 get_last_projection() { - return copy_matrix(gGLLastProjection); + return glm::make_mat4(gGLLastProjection); } -void copy_matrix(const glh::matrix4f& src, F32* dst) +void copy_matrix(const glm::mat4& src, F32* dst) { + auto matp = glm::value_ptr(src); for (U32 i = 0; i < 16; i++) { - dst[i] = src.m[i]; + dst[i] = matp[i]; } } -void set_current_modelview(const glh::matrix4f& mat) +void set_current_modelview(const glm::mat4& mat) { copy_matrix(mat, gGLModelView); } -void set_current_projection(glh::matrix4f& mat) +void set_current_projection(const glm::mat4& mat) { copy_matrix(mat, gGLProjection); } -glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar) +void set_last_modelview(const glm::mat4& mat) { - glh::matrix4f ret( - 2.f/(right-left), 0.f, 0.f, -(right+left)/(right-left), - 0.f, 2.f/(top-bottom), 0.f, -(top+bottom)/(top-bottom), - 0.f, 0.f, -2.f/(zfar-znear), -(zfar+znear)/(zfar-znear), - 0.f, 0.f, 0.f, 1.f); - - return ret; + copy_matrix(mat, gGLLastModelView); } -glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar) +void set_last_projection(const glm::mat4& mat) { - GLfloat f = 1.f/tanf(DEG_TO_RAD*fovy/2.f); - - return glh::matrix4f(f/aspect, 0, 0, 0, - 0, f, 0, 0, - 0, 0, (zFar+zNear)/(zNear-zFar), (2.f*zFar*zNear)/(zNear-zFar), - 0, 0, -1.f, 0); + copy_matrix(mat, gGLLastProjection); } -glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up) +glm::vec3 mul_mat4_vec3(const glm::mat4& mat, const glm::vec3& vec) { - LLVector3 f = center-eye; - f.normVec(); - up.normVec(); - LLVector3 s = f % up; - LLVector3 u = s % f; + //const float w = vec[0] * mat[0][3] + vec[1] * mat[1][3] + vec[2] * mat[2][3] + mat[3][3]; + //return glm::vec3( + // (vec[0] * mat[0][0] + vec[1] * mat[1][0] + vec[2] * mat[2][0] + mat[3][0]) / w, + // (vec[0] * mat[0][1] + vec[1] * mat[1][1] + vec[2] * mat[2][1] + mat[3][1]) / w, + // (vec[0] * mat[0][2] + vec[1] * mat[1][2] + vec[2] * mat[2][2] + mat[3][2]) / w + //); + LLVector4a x, y, z, s, t, p, q; + + x.splat(vec.x); + y.splat(vec.y); + z.splat(vec.z); + + s.splat<3>(mat[0].data); + t.splat<3>(mat[1].data); + p.splat<3>(mat[2].data); + q.splat<3>(mat[3].data); + + s.mul(x); + t.mul(y); + p.mul(z); + q.add(s); + t.add(p); + q.add(t); - return glh::matrix4f(s[0], s[1], s[2], 0, - u[0], u[1], u[2], 0, - -f[0], -f[1], -f[2], 0, - 0, 0, 0, 1); + x.mul(mat[0].data); + y.mul(mat[1].data); + z.mul(mat[2].data); + x.add(y); + z.add(mat[3].data); + LLVector4a res; + res.load3(glm::value_ptr(vec)); + res.setAdd(x, z); + res.div(q); + return glm::make_vec3(res.getF32ptr()); } diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 39c13e328a..2645597b1a 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -42,7 +42,7 @@ #include "llpointer.h" #include "llglheaders.h" #include "llmatrix4a.h" -#include "glh/glh_linear.h" +#include "glm/mat4x4.hpp" #include #include @@ -401,8 +401,8 @@ public: void matrixMode(eMatrixMode mode); eMatrixMode getMatrixMode(); - const glh::matrix4f& getModelviewMatrix(); - const glh::matrix4f& getProjectionMatrix(); + const glm::mat4& getModelviewMatrix(); + const glm::mat4& getProjectionMatrix(); void syncMatrices(); void syncLightState(); @@ -502,7 +502,7 @@ private: eMatrixMode mMatrixMode; U32 mMatIdx[NUM_MATRIX_MODES]; U32 mMatHash[NUM_MATRIX_MODES]; - glh::matrix4f mMatrix[NUM_MATRIX_MODES][LL_MATRIX_STACK_DEPTH]; + glm::mat4 mMatrix[NUM_MATRIX_MODES][LL_MATRIX_STACK_DEPTH]; U32 mCurMatHash[NUM_MATRIX_MODES]; U32 mLightHash; LLColor4 mAmbientLightColor; @@ -536,8 +536,8 @@ extern F32 gGLLastModelView[16]; extern F32 gGLLastProjection[16]; extern F32 gGLProjection[16]; extern S32 gGLViewport[4]; -extern F32 gGLDeltaModelView[16]; -extern F32 gGLInverseDeltaModelView[16]; +extern glm::mat4 gGLDeltaModelView; +extern glm::mat4 gGLInverseDeltaModelView; extern thread_local LLRender gGL; @@ -548,19 +548,20 @@ const F32 OGL_TO_CFR_ROTATION[16] = { 0.f, 0.f, -1.f, 0.f, // -Z becomes X 0.f, 1.f, 0.f, 0.f, // Y becomes Z 0.f, 0.f, 0.f, 1.f }; -glh::matrix4f copy_matrix(F32* src); -glh::matrix4f get_current_modelview(); -glh::matrix4f get_current_projection(); -glh::matrix4f get_last_modelview(); -glh::matrix4f get_last_projection(); +glm::mat4 copy_matrix(F32* src); +glm::mat4 get_current_modelview(); +glm::mat4 get_current_projection(); +glm::mat4 get_last_modelview(); +glm::mat4 get_last_projection(); -void copy_matrix(const glh::matrix4f& src, F32* dst); -void set_current_modelview(const glh::matrix4f& mat); -void set_current_projection(glh::matrix4f& mat); +void copy_matrix(const glm::mat4& src, F32* dst); +void set_current_modelview(const glm::mat4& mat); +void set_current_projection(const glm::mat4& mat); +void set_last_modelview(const glm::mat4& mat); +void set_last_projection(const glm::mat4& mat); -glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar); -glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar); -glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up); +// glh compat +glm::vec3 mul_mat4_vec3(const glm::mat4& mat, const glm::vec3& vec); #define LL_SHADER_LOADING_WARNS(...) LL_WARNS() diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 666d792d1d..8524b470de 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -36,6 +36,7 @@ #include "llshadermgr.h" #include "llglslshader.h" #include "llmemory.h" +#include //Next Highest Power Of Two //helper function, returns first number > v that is a power of 2, or v if v is already a power of 2 @@ -590,13 +591,13 @@ void LLVertexBufferData::draw() gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.pushMatrix(); - gGL.loadMatrix(mModelView.m); + gGL.loadMatrix(glm::value_ptr(mModelView)); gGL.matrixMode(LLRender::MM_PROJECTION); gGL.pushMatrix(); - gGL.loadMatrix(mProjection.m); + gGL.loadMatrix(glm::value_ptr(mProjection)); gGL.matrixMode(LLRender::MM_TEXTURE0); gGL.pushMatrix(); - gGL.loadMatrix(mTexture0.m); + gGL.loadMatrix(glm::value_ptr(mTexture0)); mVB->setBuffer(); diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 9fe468f89e..d4c6fbaf18 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -38,6 +38,7 @@ #include #include #include +#include #define LL_MAX_VERTEX_ATTRIB_LOCATION 64 @@ -63,8 +64,11 @@ public: , mMode(0) , mCount(0) , mTexName(0) + , mProjection(glm::identity()) + , mModelView(glm::identity()) + , mTexture0(glm::identity()) {} - LLVertexBufferData(LLVertexBuffer* buffer, U8 mode, U32 count, U32 tex_name, glh::matrix4f model_view, glh::matrix4f projection, glh::matrix4f texture0) + LLVertexBufferData(LLVertexBuffer* buffer, U8 mode, U32 count, U32 tex_name, const glm::mat4& model_view, const glm::mat4& projection, const glm::mat4& texture0) : mVB(buffer) , mMode(mode) , mCount(count) @@ -78,9 +82,9 @@ public: U8 mMode; U32 mCount; U32 mTexName; - glh::matrix4f mProjection; - glh::matrix4f mModelView; - glh::matrix4f mTexture0; + glm::mat4 mProjection; + glm::mat4 mModelView; + glm::mat4 mTexture0; }; typedef std::list buffer_data_list_t; -- cgit v1.2.3 From 74205607b7e106f3b7566ef4a4b9c2fcdfa2f83e Mon Sep 17 00:00:00 2001 From: Ansariel Hiller Date: Fri, 13 Sep 2024 16:28:48 +0200 Subject: Clean up Windows build (#2562) * APR_DECLARE_STATIC and APU_DECLARE_STATIC gets already defined in APR.cmake * Move both _CRT_SECURE_NO_WARNINGS and _WINSOCK_DEPRECATED_NO_WARNINGS definitions to 00-Common.cmake * Always define WIN32_LEAN_AND_MEAN and include subset of Windows API by default * Remove llwin32headerslean.h and remove unnecessary WIN32_LEAN_AND_MEAN definition handling in llwin32headers.h * Clean up includes of Windows API headers * Get rid of workaround to link against IPHLPAPI.lib in lluuid.cpp - this seems to have been an issue in the past that has been fixed --- indra/llrender/llglheaders.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index c5e1ff3e23..3d4dc5e698 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -46,7 +46,7 @@ // LL_WINDOWS // windows gl headers depend on things like APIENTRY, so include windows. -#include "llwin32headerslean.h" +#include "llwin32headers.h" //---------------------------------------------------------------------------- #include -- cgit v1.2.3 From 486613e79bb96b838121f627ef73b1293ee18c12 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 16 Sep 2024 18:49:03 -0500 Subject: Profile guided optimization pass (#2582) - Tune up LLJointRiggingInfoTab - Visualize joint bounding boxes when visualizing joints - Use LLJointRiggingInfo to caclulate desired resolution of a texture - Throttle calls to calcPixelArea - Fetch MeshSkinInfo immediately when header is received --- indra/llrender/llrendersphere.cpp | 62 +++++++++++++++++++++++++++++++-------- indra/llrender/llrendersphere.h | 1 + indra/llrender/llvertexbuffer.cpp | 2 -- 3 files changed, 51 insertions(+), 14 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llrendersphere.cpp b/indra/llrender/llrendersphere.cpp index 9570180554..cd8ef7d68e 100644 --- a/indra/llrender/llrendersphere.cpp +++ b/indra/llrender/llrendersphere.cpp @@ -34,6 +34,8 @@ #include "llerror.h" #include "llglheaders.h" +#include "llvertexbuffer.h" +#include "llglslshader.h" LLRenderSphere gSphere; @@ -53,12 +55,20 @@ inline LLVector3 polar_to_cart(F32 latitude, F32 longitude) void LLRenderSphere::renderGGL() { + LL_PROFILE_ZONE_SCOPED; S32 const LATITUDE_SLICES = 20; S32 const LONGITUDE_SLICES = 30; - if (mSpherePoints.empty()) + if (mVertexBuffer.isNull()) { mSpherePoints.resize(LATITUDE_SLICES + 1); + mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX); + + mVertexBuffer->allocateBuffer((U32)(LATITUDE_SLICES + 1) * (LONGITUDE_SLICES + 1), LATITUDE_SLICES * LONGITUDE_SLICES * 6); + + LLStrider v; + mVertexBuffer->getVertexStrider(v); + for (S32 lat_i = 0; lat_i < LATITUDE_SLICES + 1; lat_i++) { mSpherePoints[lat_i].resize(LONGITUDE_SLICES + 1); @@ -68,24 +78,52 @@ void LLRenderSphere::renderGGL() F32 lon = (F32)lon_i / LONGITUDE_SLICES; mSpherePoints[lat_i][lon_i] = polar_to_cart(lat, lon); + v[lat_i * (LONGITUDE_SLICES + 1) + lon_i] = mSpherePoints[lat_i][lon_i]; } } + + LLStrider i; + mVertexBuffer->getIndexStrider(i); + + for (S32 lat_i = 0; lat_i < LATITUDE_SLICES; lat_i++) + { + for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES; lon_i++) + { + i[(lat_i * LONGITUDE_SLICES + lon_i) * 6 + 0] = lat_i * (LONGITUDE_SLICES + 1) + lon_i; + i[(lat_i * LONGITUDE_SLICES + lon_i) * 6 + 1] = lat_i * (LONGITUDE_SLICES + 1) + lon_i + 1; + i[(lat_i * LONGITUDE_SLICES + lon_i) * 6 + 2] = (lat_i + 1) * (LONGITUDE_SLICES + 1) + lon_i; + + i[(lat_i * LONGITUDE_SLICES + lon_i) * 6 + 3] = (lat_i + 1) * (LONGITUDE_SLICES + 1) + lon_i; + i[(lat_i * LONGITUDE_SLICES + lon_i) * 6 + 4] = lat_i * (LONGITUDE_SLICES + 1) + lon_i + 1; + i[(lat_i * LONGITUDE_SLICES + lon_i) * 6 + 5] = (lat_i + 1) * (LONGITUDE_SLICES + 1) + lon_i + 1; + } + } + + mVertexBuffer->unmapBuffer(); } - gGL.begin(LLRender::TRIANGLES); - for (S32 lat_i = 0; lat_i < LATITUDE_SLICES; lat_i++) - { - for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES; lon_i++) + if (LLGLSLShader::sCurBoundShaderPtr->mAttributeMask == LLVertexBuffer::MAP_VERTEX) + { // shader expects only vertex positions in vertex buffer, use fast path + mVertexBuffer->setBuffer(); + mVertexBuffer->drawRange(LLRender::TRIANGLES, 0, mVertexBuffer->getNumVerts(), mVertexBuffer->getNumIndices(), 0); + } + else + { //shader wants colors in the vertex stream, use slow path + gGL.begin(LLRender::TRIANGLES); + for (S32 lat_i = 0; lat_i < LATITUDE_SLICES; lat_i++) { - gGL.vertex3fv(mSpherePoints[lat_i][lon_i].mV); - gGL.vertex3fv(mSpherePoints[lat_i][lon_i+1].mV); - gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i].mV); + for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES; lon_i++) + { + gGL.vertex3fv(mSpherePoints[lat_i][lon_i].mV); + gGL.vertex3fv(mSpherePoints[lat_i][lon_i + 1].mV); + gGL.vertex3fv(mSpherePoints[lat_i + 1][lon_i].mV); - gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i].mV); - gGL.vertex3fv(mSpherePoints[lat_i][lon_i+1].mV); - gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i+1].mV); + gGL.vertex3fv(mSpherePoints[lat_i + 1][lon_i].mV); + gGL.vertex3fv(mSpherePoints[lat_i][lon_i + 1].mV); + gGL.vertex3fv(mSpherePoints[lat_i + 1][lon_i + 1].mV); + } } + gGL.end(); } - gGL.end(); } diff --git a/indra/llrender/llrendersphere.h b/indra/llrender/llrendersphere.h index e2e886fa06..5b6eabecb8 100644 --- a/indra/llrender/llrendersphere.h +++ b/indra/llrender/llrendersphere.h @@ -45,6 +45,7 @@ public: private: std::vector< std::vector > mSpherePoints; + LLPointer mVertexBuffer; }; extern LLRenderSphere gSphere; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 3a18c28a62..e9fa369b0c 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -1341,8 +1341,6 @@ void LLVertexBuffer::unmapBuffer() void LLVertexBuffer::_mapBuffer() { - // must only be called from main thread - llassert(LLCoros::on_main_thread_main_coro()); if (!mMapped) { mMapped = true; -- cgit v1.2.3 From 0a617904f98ab5960379099822e4891a08137e68 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 17 Sep 2024 18:14:22 -0500 Subject: #2590 Fix for horrible FPS on Intel Mac (#2591) * Work around for GHA mac runners not playing nice with Tracy * Delay VBO deletion for a few frames * Enable multithreaded GL driver and multithreaded media textures on Apple silicon --- indra/llrender/llgl.cpp | 5 + indra/llrender/llgl.h | 1 + indra/llrender/llvertexbuffer.cpp | 374 +++++++++++++++++++++----------------- 3 files changed, 217 insertions(+), 163 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index c62cacdce6..c5c9d50dee 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -1170,6 +1170,11 @@ bool LLGLManager::initGL() mGLVendorShort = "INTEL"; mIsIntel = true; } + else if (mGLVendor.find("APPLE") != std::string::npos) + { + mGLVendorShort = "APPLE"; + mIsApple = true; + } else { mGLVendorShort = "MISC"; diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 17f825bd71..f5b1e8d786 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -102,6 +102,7 @@ public: bool mIsAMD; bool mIsNVIDIA; bool mIsIntel; + bool mIsApple = false; // hints to the render pipe U32 mDownScaleMethod = 0; // see settings.xml RenderDownScaleMethod diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index e9fa369b0c..0be799db9d 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -289,22 +289,58 @@ static GLuint gen_buffer() return ret; } -#define ANALYZE_VBO_POOL 0 +static void delete_buffers(S32 count, GLuint* buffers) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; + // wait a few frames before actually deleting the buffers to avoid + // synchronization issues with the GPU + static std::vector sFreeList[4]; + + if (gGLManager.mInited) + { + U32 idx = LLImageGL::sFrameCount % 4; + + for (S32 i = 0; i < count; ++i) + { + sFreeList[idx].push_back(buffers[i]); + } + + idx = (LLImageGL::sFrameCount + 3) % 4; + + if (!sFreeList[idx].empty()) + { + glDeleteBuffers((GLsizei)sFreeList[idx].size(), sFreeList[idx].data()); + sFreeList[idx].resize(0); + } + } +} -#if LL_DARWIN -// experimental -- disable VBO pooling on OS X and use glMapBuffer +#define ANALYZE_VBO_POOL 0 + +// VBO Pool interface class LLVBOPool +{ + public: + virtual ~LLVBOPool() = default; + virtual void allocate(GLenum type, U32 size, GLuint& name, U8*& data) = 0; + virtual void free(GLenum type, U32 size, GLuint name, U8* data) = 0; + virtual U64 getVramBytesUsed() = 0; +}; + +// VBO Pool for Apple GPUs (as in M1/M2 etc, not Intel macs) +// Effectively disables VBO pooling +class LLAppleVBOPool final: public LLVBOPool { public: U64 mAllocated = 0; - U64 getVramBytesUsed() + U64 getVramBytesUsed() override { return mAllocated; } - void allocate(GLenum type, U32 size, GLuint& name, U8*& data) + void allocate(GLenum type, U32 size, GLuint& name, U8*& data) override { LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; STOP_GLERROR; @@ -324,7 +360,7 @@ public: } } - void free(GLenum type, U32 size, GLuint name, U8* data) + void free(GLenum type, U32 size, GLuint name, U8* data) override { LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; llassert(type == GL_ARRAY_BUFFER || type == GL_ELEMENT_ARRAY_BUFFER); @@ -339,19 +375,17 @@ public: STOP_GLERROR; if (name) { - glDeleteBuffers(1, &name); + delete_buffers(1, &name); } STOP_GLERROR; } }; -#else - -class LLVBOPool +// VBO Pool for GPUs that benefit from VBO pooling +class LLDefaultVBOPool final : public LLVBOPool { public: typedef std::chrono::steady_clock::time_point Time; - struct Entry { U8* mData; @@ -359,7 +393,7 @@ public: Time mAge; }; - ~LLVBOPool() + ~LLDefaultVBOPool() override { clear(); } @@ -377,7 +411,7 @@ public: U32 mMisses = 0; U32 mHits = 0; - U64 getVramBytesUsed() + U64 getVramBytesUsed() override { return mAllocated + mReserved; } @@ -393,7 +427,7 @@ public: size += block_size - (size % block_size); } - void allocate(GLenum type, U32 size, GLuint& name, U8*& data) + void allocate(GLenum type, U32 size, GLuint& name, U8*& data) override { LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; llassert(type == GL_ARRAY_BUFFER || type == GL_ELEMENT_ARRAY_BUFFER); @@ -449,7 +483,7 @@ public: clean(); } - void free(GLenum type, U32 size, GLuint name, U8* data) + void free(GLenum type, U32 size, GLuint name, U8* data) override { LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; llassert(type == GL_ARRAY_BUFFER || type == GL_ELEMENT_ARRAY_BUFFER); @@ -512,7 +546,7 @@ public: LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vbo cache timeout"); auto& entry = entries.back(); ll_aligned_free_16(entry.mData); - glDeleteBuffers(1, &entry.mGLName); + delete_buffers(1, &entry.mGLName); llassert(mReserved >= iter->first); mReserved -= iter->first; entries.pop_back(); @@ -548,7 +582,7 @@ public: for (auto& entry : entries.second) { ll_aligned_free_16(entry.mData); - glDeleteBuffers(1, &entry.mGLName); + delete_buffers(1, &entry.mGLName); } } @@ -557,7 +591,7 @@ public: for (auto& entry : entries.second) { ll_aligned_free_16(entry.mData); - glDeleteBuffers(1, &entry.mGLName); + delete_buffers(1, &entry.mGLName); } } @@ -567,7 +601,6 @@ public: mVBOPool.clear(); } }; -#endif static LLVBOPool* sVBOPool = nullptr; @@ -896,7 +929,16 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const void LLVertexBuffer::initClass(LLWindow* window) { llassert(sVBOPool == nullptr); - sVBOPool = new LLVBOPool(); + if (gGLManager.mIsApple) + { + LL_INFOS() << "VBO Pooling Disabled" << LL_ENDL; + sVBOPool = new LLAppleVBOPool(); + } + else + { + LL_INFOS() << "VBO Pooling Enabled" << LL_ENDL; + sVBOPool = new LLDefaultVBOPool(); + } #if ENABLE_GL_WORK_QUEUE sQueue = new GLWorkQueue(); @@ -964,7 +1006,6 @@ void LLVertexBuffer::flushBuffers() { LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; // must only be called from main thread - llassert(LLCoros::on_main_thread_main_coro()); for (auto& buffer : sMappedBuffers) { buffer->_unmapBuffer(); @@ -1231,28 +1272,29 @@ U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 inde count = mNumVerts - index; } -#if !LL_DARWIN - U32 start = mOffsets[type] + sTypeSize[type] * index; - U32 end = start + sTypeSize[type] * count-1; - - bool flagged = false; - // flag region as mapped - for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) + if (!gGLManager.mIsApple) { - MappedRegion& region = mMappedVertexRegions[i]; - if (expand_region(region, start, end)) + U32 start = mOffsets[type] + sTypeSize[type] * index; + U32 end = start + sTypeSize[type] * count-1; + + bool flagged = false; + // flag region as mapped + for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) { - flagged = true; - break; + MappedRegion& region = mMappedVertexRegions[i]; + if (expand_region(region, start, end)) + { + flagged = true; + break; + } } - } - if (!flagged) - { - //didn't expand an existing region, make a new one - mMappedVertexRegions.push_back({ start, end }); + if (!flagged) + { + //didn't expand an existing region, make a new one + mMappedVertexRegions.push_back({ start, end }); + } } -#endif return mMappedData+mOffsets[type]+sTypeSize[type]*index; } @@ -1267,28 +1309,29 @@ U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count) count = mNumIndices-index; } -#if !LL_DARWIN - U32 start = sizeof(U16) * index; - U32 end = start + sizeof(U16) * count-1; - - bool flagged = false; - // flag region as mapped - for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) + if (!gGLManager.mIsApple) { - MappedRegion& region = mMappedIndexRegions[i]; - if (expand_region(region, start, end)) + U32 start = sizeof(U16) * index; + U32 end = start + sizeof(U16) * count-1; + + bool flagged = false; + // flag region as mapped + for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) { - flagged = true; - break; + MappedRegion& region = mMappedIndexRegions[i]; + if (expand_region(region, start, end)) + { + flagged = true; + break; + } } - } - if (!flagged) - { - //didn't expand an existing region, make a new one - mMappedIndexRegions.push_back({ start, end }); + if (!flagged) + { + //didn't expand an existing region, make a new one + mMappedIndexRegions.push_back({ start, end }); + } } -#endif return mMappedIndexData + sizeof(U16)*index; } @@ -1301,37 +1344,40 @@ U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count) // dst -- mMappedData or mMappedIndexData void LLVertexBuffer::flush_vbo(GLenum target, U32 start, U32 end, void* data, U8* dst) { -#if LL_DARWIN - // on OS X, flush_vbo doesn't actually write to the GL buffer, so be sure to call - // _mapBuffer to tag the buffer for flushing to GL - _mapBuffer(); - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb memcpy"); - STOP_GLERROR; - // copy into mapped buffer - memcpy(dst+start, data, end-start+1); -#else - llassert(target == GL_ARRAY_BUFFER ? sGLRenderBuffer == mGLBuffer : sGLRenderIndices == mGLIndices); - - // skip mapped data and stream to GPU via glBufferSubData - if (end != 0) + if (gGLManager.mIsApple) { - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("glBufferSubData"); - LL_PROFILE_ZONE_NUM(start); - LL_PROFILE_ZONE_NUM(end); - LL_PROFILE_ZONE_NUM(end-start); - - constexpr U32 block_size = 65536; + // on OS X, flush_vbo doesn't actually write to the GL buffer, so be sure to call + // _mapBuffer to tag the buffer for flushing to GL + _mapBuffer(); + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb memcpy"); + STOP_GLERROR; + // copy into mapped buffer + memcpy(dst+start, data, end-start+1); + } + else + { + llassert(target == GL_ARRAY_BUFFER ? sGLRenderBuffer == mGLBuffer : sGLRenderIndices == mGLIndices); - for (U32 i = start; i <= end; i += block_size) + // skip mapped data and stream to GPU via glBufferSubData + if (end != 0) { - //LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("glBufferSubData block"); - //LL_PROFILE_GPU_ZONE("glBufferSubData"); - U32 tend = llmin(i + block_size, end); - U32 size = tend - i + 1; - glBufferSubData(target, i, size, (U8*) data + (i-start)); + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("glBufferSubData"); + LL_PROFILE_ZONE_NUM(start); + LL_PROFILE_ZONE_NUM(end); + LL_PROFILE_ZONE_NUM(end-start); + + constexpr U32 block_size = 65536; + + for (U32 i = start; i <= end; i += block_size) + { + //LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("glBufferSubData block"); + //LL_PROFILE_GPU_ZONE("glBufferSubData"); + U32 tend = llmin(i + block_size, end); + U32 size = tend - i + 1; + glBufferSubData(target, i, size, (U8*) data + (i-start)); + } } } -#endif } void LLVertexBuffer::unmapBuffer() @@ -1364,114 +1410,116 @@ void LLVertexBuffer::_unmapBuffer() } }; -#if LL_DARWIN - STOP_GLERROR; - if (mMappedData) - { - if (mGLBuffer) - { - glDeleteBuffers(1, &mGLBuffer); - } - mGLBuffer = gen_buffer(); - glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); - sGLRenderBuffer = mGLBuffer; - glBufferData(GL_ARRAY_BUFFER, mSize, mMappedData, GL_STATIC_DRAW); - } - else if (mGLBuffer != sGLRenderBuffer) - { - glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); - sGLRenderBuffer = mGLBuffer; - } - STOP_GLERROR; - - if (mMappedIndexData) + if (gGLManager.mIsApple) { - if (mGLIndices) + STOP_GLERROR; + if (mMappedData) { - glDeleteBuffers(1, &mGLIndices); + if (mGLBuffer) + { + delete_buffers(1, &mGLBuffer); + } + mGLBuffer = gen_buffer(); + glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); + sGLRenderBuffer = mGLBuffer; + glBufferData(GL_ARRAY_BUFFER, mSize, mMappedData, GL_STATIC_DRAW); } - - mGLIndices = gen_buffer(); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); - sGLRenderIndices = mGLIndices; - - glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndicesSize, mMappedIndexData, GL_STATIC_DRAW); - } - else if (mGLIndices != sGLRenderIndices) - { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); - sGLRenderIndices = mGLIndices; - } - STOP_GLERROR; -#else - - if (!mMappedVertexRegions.empty()) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - vertex"); - - if (sGLRenderBuffer != mGLBuffer) + else if (mGLBuffer != sGLRenderBuffer) { glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); sGLRenderBuffer = mGLBuffer; } + STOP_GLERROR; - U32 start = 0; - U32 end = 0; - - std::sort(mMappedVertexRegions.begin(), mMappedVertexRegions.end(), SortMappedRegion()); - - for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) + if (mMappedIndexData) { - const MappedRegion& region = mMappedVertexRegions[i]; - if (region.mStart == end + 1) - { - end = region.mEnd; - } - else + if (mGLIndices) { - flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start, mMappedData); - start = region.mStart; - end = region.mEnd; + delete_buffers(1, &mGLIndices); } - } - - flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start, mMappedData); - mMappedVertexRegions.clear(); - } - if (!mMappedIndexRegions.empty()) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - index"); + mGLIndices = gen_buffer(); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); + sGLRenderIndices = mGLIndices; - if (mGLIndices != sGLRenderIndices) + glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndicesSize, mMappedIndexData, GL_STATIC_DRAW); + } + else if (mGLIndices != sGLRenderIndices) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); sGLRenderIndices = mGLIndices; } - U32 start = 0; - U32 end = 0; + STOP_GLERROR; + } + else + { + if (!mMappedVertexRegions.empty()) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - vertex"); + + if (sGLRenderBuffer != mGLBuffer) + { + glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); + sGLRenderBuffer = mGLBuffer; + } - std::sort(mMappedIndexRegions.begin(), mMappedIndexRegions.end(), SortMappedRegion()); + U32 start = 0; + U32 end = 0; - for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) + std::sort(mMappedVertexRegions.begin(), mMappedVertexRegions.end(), SortMappedRegion()); + + for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) + { + const MappedRegion& region = mMappedVertexRegions[i]; + if (region.mStart == end + 1) + { + end = region.mEnd; + } + else + { + flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start, mMappedData); + start = region.mStart; + end = region.mEnd; + } + } + + flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start, mMappedData); + mMappedVertexRegions.clear(); + } + + if (!mMappedIndexRegions.empty()) { - const MappedRegion& region = mMappedIndexRegions[i]; - if (region.mStart == end + 1) + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - index"); + + if (mGLIndices != sGLRenderIndices) { - end = region.mEnd; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); + sGLRenderIndices = mGLIndices; } - else + U32 start = 0; + U32 end = 0; + + std::sort(mMappedIndexRegions.begin(), mMappedIndexRegions.end(), SortMappedRegion()); + + for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) { - flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start, mMappedIndexData); - start = region.mStart; - end = region.mEnd; + const MappedRegion& region = mMappedIndexRegions[i]; + if (region.mStart == end + 1) + { + end = region.mEnd; + } + else + { + flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start, mMappedIndexData); + start = region.mStart; + end = region.mEnd; + } } - } - flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start, mMappedIndexData); - mMappedIndexRegions.clear(); + flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start, mMappedIndexData); + mMappedIndexRegions.clear(); + } } -#endif } //---------------------------------------------------------------------------- -- cgit v1.2.3 From 3327ae7938499c4410556bef24662bb9f65274e8 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 17 Sep 2024 18:46:44 +0300 Subject: Convert image drawing logic from quads to triangles --- indra/llrender/llrender2dutils.cpp | 284 ++++++++++++++++++++++++------------- 1 file changed, 187 insertions(+), 97 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index 428370057e..a63f3c1ef9 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -429,165 +429,247 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex gGL.color4fv(color.mV); - const S32 NUM_VERTICES = 9 * 4; // 9 quads - LLVector2 uv[NUM_VERTICES]; - LLVector3 pos[NUM_VERTICES]; + constexpr S32 NUM_VERTICES = 9 * 2 * 3; // 9 quads, 2 triangles per quad, 3 vertices per triangle + static thread_local LLVector2 uv[NUM_VERTICES]; + static thread_local LLVector3 pos[NUM_VERTICES]; S32 index = 0; - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { - // draw bottom left - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f); + // draw bottom left triangles + // 1 + uv[index].set(uv_outer_rect.mLeft, uv_outer_rect.mBottom); + pos[index].set(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); + uv[index].set(uv_center_rect.mLeft, uv_outer_rect.mBottom); + pos[index].set(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + uv[index].set(uv_center_rect.mLeft, uv_center_rect.mBottom); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); + // 2 + uv[index].set(uv_outer_rect.mLeft, uv_outer_rect.mBottom); + pos[index].set(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f); index++; - // draw bottom middle - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); + uv[index].set(uv_center_rect.mLeft, uv_center_rect.mBottom); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); + uv[index].set(uv_outer_rect.mLeft, uv_center_rect.mBottom); + pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + // draw bottom middle triangles + uv[index].set(uv_center_rect.mLeft, uv_outer_rect.mBottom); + pos[index].set(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + uv[index].set(uv_center_rect.mRight, uv_outer_rect.mBottom); + pos[index].set(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); index++; - // draw bottom right - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); + uv[index].set(uv_center_rect.mRight, uv_center_rect.mBottom); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f); + // 2 + uv[index].set(uv_center_rect.mLeft, uv_outer_rect.mBottom); + pos[index].set(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); + uv[index].set(uv_center_rect.mRight, uv_center_rect.mBottom); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + uv[index].set(uv_center_rect.mLeft, uv_center_rect.mBottom); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; - // draw left - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); + // draw bottom right triangles + uv[index].set(uv_center_rect.mRight, uv_outer_rect.mBottom); + pos[index].set(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + uv[index].set(uv_outer_rect.mRight, uv_outer_rect.mBottom); + pos[index].set(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + uv[index].set(uv_outer_rect.mRight, uv_center_rect.mBottom); + pos[index].set(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); + // 2 + uv[index].set(uv_center_rect.mRight, uv_outer_rect.mBottom); + pos[index].set(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); index++; - // draw middle - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + uv[index].set(uv_outer_rect.mRight, uv_center_rect.mBottom); + pos[index].set(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + uv[index].set(uv_center_rect.mRight, uv_center_rect.mBottom); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + // draw left triangles + uv[index].set(uv_outer_rect.mLeft, uv_center_rect.mBottom); + pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + uv[index].set(uv_center_rect.mLeft, uv_center_rect.mBottom); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; - // draw right - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + uv[index].set(uv_center_rect.mLeft, uv_center_rect.mTop); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); + // 2 + uv[index].set(uv_outer_rect.mLeft, uv_center_rect.mBottom); + pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); + uv[index].set(uv_center_rect.mLeft, uv_center_rect.mTop); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + uv[index].set(uv_outer_rect.mLeft, uv_center_rect.mTop); + pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); index++; - // draw top left - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); + // draw middle triangles + uv[index].set(uv_center_rect.mLeft, uv_center_rect.mBottom); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + uv[index].set(uv_center_rect.mRight, uv_center_rect.mBottom); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); + uv[index].set(uv_center_rect.mRight, uv_center_rect.mTop); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f); + // 2 + uv[index].set(uv_center_rect.mLeft, uv_center_rect.mBottom); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; - // draw top middle - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + uv[index].set(uv_center_rect.mRight, uv_center_rect.mTop); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + uv[index].set(uv_center_rect.mLeft, uv_center_rect.mTop); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); + // draw right triangles + uv[index].set(uv_center_rect.mRight, uv_center_rect.mBottom); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); + uv[index].set(uv_outer_rect.mRight, uv_center_rect.mBottom); + pos[index].set(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); index++; - // draw top right - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + uv[index].set(uv_outer_rect.mRight, uv_center_rect.mTop); + pos[index].set(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + // 2 + uv[index].set(uv_center_rect.mRight, uv_center_rect.mBottom); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + index++; + + uv[index].set(uv_outer_rect.mRight, uv_center_rect.mTop); + pos[index].set(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + uv[index].set(uv_center_rect.mRight, uv_center_rect.mTop); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + // draw top left triangles + uv[index].set(uv_outer_rect.mLeft, uv_center_rect.mTop); + pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + uv[index].set(uv_center_rect.mLeft, uv_center_rect.mTop); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + uv[index].set(uv_center_rect.mLeft, uv_outer_rect.mTop); + pos[index].set(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); + index++; + + // 2 + uv[index].set(uv_outer_rect.mLeft, uv_center_rect.mTop); + pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + uv[index].set(uv_center_rect.mLeft, uv_outer_rect.mTop); + pos[index].set(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); + uv[index].set(uv_outer_rect.mLeft, uv_outer_rect.mTop); + pos[index].set(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f); + // draw top middle triangles + uv[index].set(uv_center_rect.mLeft, uv_center_rect.mTop); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); + uv[index].set(uv_center_rect.mRight, uv_center_rect.mTop); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + uv[index].set(uv_center_rect.mRight, uv_outer_rect.mTop); + pos[index].set(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); + index++; + + // 2 + uv[index].set(uv_center_rect.mLeft, uv_center_rect.mTop); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + uv[index].set(uv_center_rect.mRight, uv_outer_rect.mTop); + pos[index].set(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); + index++; + + uv[index].set(uv_center_rect.mLeft, uv_outer_rect.mTop); + pos[index].set(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); + index++; + + // draw top right triangles + uv[index].set(uv_center_rect.mRight, uv_center_rect.mTop); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + uv[index].set(uv_outer_rect.mRight, uv_center_rect.mTop); + pos[index].set(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + uv[index].set(uv_outer_rect.mRight, uv_outer_rect.mTop); + pos[index].set(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f); + index++; + + // 2 + uv[index].set(uv_center_rect.mRight, uv_center_rect.mTop); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + uv[index].set(uv_outer_rect.mRight, uv_outer_rect.mTop); + pos[index].set(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f); + index++; + + uv[index].set(uv_center_rect.mRight, uv_outer_rect.mTop); + pos[index].set(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); index++; gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); @@ -629,11 +711,11 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre if (degrees == 0.f) { - const S32 NUM_VERTICES = 4; // 9 quads - LLVector2 uv[NUM_VERTICES]; - LLVector3 pos[NUM_VERTICES]; + constexpr S32 NUM_VERTICES = 2 * 3; + static thread_local LLVector2 uv[NUM_VERTICES]; + static thread_local LLVector3 pos[NUM_VERTICES]; - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { LLVector3 ui_scale = gGL.getUIScale(); LLVector3 ui_translation = gGL.getUITranslation(); @@ -644,20 +726,28 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre S32 scaled_width = ll_round(width * ui_scale.mV[VX]); S32 scaled_height = ll_round(height * ui_scale.mV[VY]); - uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); - pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f); + uv[index].set(uv_rect.mRight, uv_rect.mTop); + pos[index].set(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f); + index++; + + uv[index].set(uv_rect.mLeft, uv_rect.mTop); + pos[index].set(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f); + index++; + + uv[index].set(uv_rect.mLeft, uv_rect.mBottom); + pos[index].set(ui_translation.mV[VX], ui_translation.mV[VY], 0.f); index++; - uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop); - pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f); + uv[index].set(uv_rect.mRight, uv_rect.mTop); + pos[index].set(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f); index++; - uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom); - pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY], 0.f); + uv[index].set(uv_rect.mLeft, uv_rect.mBottom); + pos[index].set(ui_translation.mV[VX], ui_translation.mV[VY], 0.f); index++; - uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom); - pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f); + uv[index].set(uv_rect.mRight, uv_rect.mBottom); + pos[index].set(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f); index++; gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); -- cgit v1.2.3 From 689d9e6935421879229909ec11b41a1524e64b33 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 17 Sep 2024 18:57:10 +0300 Subject: More quad to triangle coverage Quads are deprecated --- indra/llrender/llrender2dutils.cpp | 196 +++++++++++++++++++++++++++++++++++-- 1 file changed, 189 insertions(+), 7 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index a63f3c1ef9..27da64cce6 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -122,10 +122,13 @@ void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, bool filled ) // Counterclockwise quad will face the viewer if( filled ) { - gGL.begin( LLRender::QUADS ); + gGL.begin( LLRender::TRIANGLES ); gGL.vertex2i(left, top); gGL.vertex2i(left, bottom); gGL.vertex2i(right, bottom); + + gGL.vertex2i(left, top); + gGL.vertex2i(right, bottom); gGL.vertex2i(right, top); gGL.end(); } @@ -777,7 +780,7 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre gGL.color4fv(color.mV); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { LLVector3 v; @@ -793,6 +796,14 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom); gGL.vertex2f(v.mV[0], v.mV[1] ); + v = LLVector3(offset_x, offset_y, 0.f) * quat; + gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop); + gGL.vertex2f(v.mV[0], v.mV[1]); + + v = LLVector3(-offset_x, -offset_y, 0.f) * quat; + gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom); + gGL.vertex2f(v.mV[0], v.mV[1]); + v = LLVector3(offset_x, -offset_y, 0.f) * quat; gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom); gGL.vertex2f(v.mV[0], v.mV[1] ); @@ -1038,7 +1049,7 @@ void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, void gl_rect_2d_simple_tex( S32 width, S32 height ) { - gGL.begin( LLRender::QUADS ); + gGL.begin( LLRender::TRIANGLES ); gGL.texCoord2f(1.f, 1.f); gGL.vertex2i(width, height); @@ -1049,6 +1060,12 @@ void gl_rect_2d_simple_tex( S32 width, S32 height ) gGL.texCoord2f(0.f, 0.f); gGL.vertex2i(0, 0); + gGL.texCoord2f(1.f, 1.f); + gGL.vertex2i(width, height); + + gGL.texCoord2f(0.f, 0.f); + gGL.vertex2i(0, 0); + gGL.texCoord2f(1.f, 0.f); gGL.vertex2i(width, 0); @@ -1057,10 +1074,13 @@ void gl_rect_2d_simple_tex( S32 width, S32 height ) void gl_rect_2d_simple( S32 width, S32 height ) { - gGL.begin( LLRender::QUADS ); + gGL.begin( LLRender::TRIANGLES ); gGL.vertex2i(width, height); gGL.vertex2i(0, height); gGL.vertex2i(0, 0); + + gGL.vertex2i(width, height); + gGL.vertex2i(0, 0); gGL.vertex2i(width, 0); gGL.end(); } @@ -1101,7 +1121,7 @@ void gl_segmented_rect_2d_tex(const S32 left, LLVector2 width_vec((F32)width, 0.f); LLVector2 height_vec(0.f, (F32)height); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { // draw bottom left gGL.texCoord2f(0.f, 0.f); @@ -1113,6 +1133,12 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); gGL.vertex2fv((border_width_left + border_height_bottom).mV); + gGL.texCoord2f(0.f, 0.f); + gGL.vertex2f(0.f, 0.f); + + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + border_height_bottom).mV); + gGL.texCoord2f(0.f, border_uv_scale.mV[VY]); gGL.vertex2fv(border_height_bottom.mV); @@ -1126,6 +1152,12 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv(border_width_left.mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); gGL.vertex2fv((border_width_left + border_height_bottom).mV); @@ -1139,6 +1171,12 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.texCoord2f(1.f, border_uv_scale.mV[VY]); gGL.vertex2fv((width_vec + border_height_bottom).mV); + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv((width_vec - border_width_right).mV); + + gGL.texCoord2f(1.f, border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec + border_height_bottom).mV); + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); @@ -1152,6 +1190,12 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); + gGL.texCoord2f(0.f, border_uv_scale.mV[VY]); + gGL.vertex2fv(border_height_bottom.mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); + gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((height_vec - border_height_top).mV); @@ -1165,6 +1209,12 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + border_height_bottom).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); @@ -1178,6 +1228,12 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((width_vec + height_vec - border_height_top).mV); + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); + + gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec + height_vec - border_height_top).mV); + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); @@ -1191,6 +1247,12 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); gGL.vertex2fv((border_width_left + height_vec).mV); + gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((height_vec - border_height_top).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((border_width_left + height_vec).mV); + gGL.texCoord2f(0.f, 1.f); gGL.vertex2fv((height_vec).mV); @@ -1204,6 +1266,12 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); gGL.vertex2fv((border_width_left + height_vec).mV); @@ -1217,6 +1285,12 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.texCoord2f(1.f, 1.f); gGL.vertex2fv((width_vec + height_vec).mV); + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f, 1.f); + gGL.vertex2fv((width_vec + height_vec).mV); + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); } @@ -1271,7 +1345,7 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, LLVector2 x_min; LLVector2 x_max; - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { if (start_fragment < middle_start) { @@ -1290,6 +1364,12 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); gGL.vertex2fv((x_max + border_height_bottom).mV); + gGL.texCoord2f(u_min, 0.f); + gGL.vertex2fv(x_min.mV); + + gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + border_height_bottom).mV); + gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + border_height_bottom).mV); @@ -1303,6 +1383,12 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + border_height_bottom).mV); + + gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + height_vec - border_height_top).mV); @@ -1316,6 +1402,12 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, gGL.texCoord2f(u_max, 1.f); gGL.vertex2fv((x_max + height_vec).mV); + gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + height_vec - border_height_top).mV); + + gGL.texCoord2f(u_max, 1.f); + gGL.vertex2fv((x_max + height_vec).mV); + gGL.texCoord2f(u_min, 1.f); gGL.vertex2fv((x_min + height_vec).mV); } @@ -1335,6 +1427,12 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); gGL.vertex2fv((x_max + border_height_bottom).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv(x_min.mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + border_height_bottom).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + border_height_bottom).mV); @@ -1348,6 +1446,12 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + border_height_bottom).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + height_vec - border_height_top).mV); @@ -1361,6 +1465,12 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); gGL.vertex2fv((x_max + height_vec).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((x_max + height_vec).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); gGL.vertex2fv((x_min + height_vec).mV); } @@ -1382,6 +1492,12 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); gGL.vertex2fv((x_max + border_height_bottom).mV); + gGL.texCoord2f(u_min, 0.f); + gGL.vertex2fv((x_min).mV); + + gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + border_height_bottom).mV); + gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + border_height_bottom).mV); @@ -1395,6 +1511,12 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + border_height_bottom).mV); + + gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + height_vec - border_height_top).mV); @@ -1408,6 +1530,12 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, gGL.texCoord2f(u_max, 1.f); gGL.vertex2fv((x_max + height_vec).mV); + gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + height_vec - border_height_top).mV); + + gGL.texCoord2f(u_max, 1.f); + gGL.vertex2fv((x_max + height_vec).mV); + gGL.texCoord2f(u_min, 1.f); gGL.vertex2fv((x_min + height_vec).mV); } @@ -1422,7 +1550,7 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv { LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { // draw bottom left gGL.texCoord2f(clip_rect.mLeft, clip_rect.mBottom); @@ -1434,6 +1562,12 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); + gGL.texCoord2f(clip_rect.mLeft, clip_rect.mBottom); + gGL.vertex3f(0.f, 0.f, 0.f); + + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom); gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV); @@ -1447,6 +1581,12 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV); + + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); @@ -1460,6 +1600,12 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV); + + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); @@ -1473,6 +1619,12 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop); gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV); @@ -1486,6 +1638,12 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); @@ -1499,6 +1657,12 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight* width_vec + center_draw_rect.mBottom * height_vec).mV); + + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); @@ -1512,6 +1676,12 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mTop* height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft* width_vec + center_draw_rect.mTop * height_vec).mV); + gGL.texCoord2f(clip_rect.mLeft, clip_rect.mTop); gGL.vertex3fv((height_vec).mV); @@ -1525,6 +1695,12 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft* width_vec + center_draw_rect.mTop * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight* width_vec + center_draw_rect.mTop * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); @@ -1538,6 +1714,12 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.texCoord2f(clip_rect.mRight, clip_rect.mTop); gGL.vertex3fv((width_vec + height_vec).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight* width_vec + center_draw_rect.mTop * height_vec).mV); + + gGL.texCoord2f(clip_rect.mRight, clip_rect.mTop); + gGL.vertex3fv((width_vec + height_vec).mV); + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV); } -- cgit v1.2.3 From d9da5bbb33ce70e3bc799ba6696c8b10de0e5f04 Mon Sep 17 00:00:00 2001 From: Ansariel Hiller Date: Wed, 18 Sep 2024 16:09:51 +0200 Subject: Remove quads rendering mode entirely (#2593) --- indra/llrender/llfontgl.cpp | 43 +++++--- indra/llrender/llfontgl.h | 2 +- indra/llrender/llrender.cpp | 212 +++++-------------------------------- indra/llrender/llrender.h | 2 - indra/llrender/llrender2dutils.cpp | 62 +++++++---- indra/llrender/llvertexbuffer.cpp | 11 +- 6 files changed, 97 insertions(+), 235 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 9721b020c7..21593b7cb4 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -271,9 +271,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons const LLFontGlyphInfo* next_glyph = NULL; 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]; + static thread_local LLVector3 vertices[GLYPH_BATCH_SIZE * 6]; + static thread_local LLVector2 uvs[GLYPH_BATCH_SIZE * 6]; + static thread_local LLColor4U colors[GLYPH_BATCH_SIZE * 6]; LLColor4U text_color(color); // Preserve the transparency to render fading emojis in fading text (e.g. @@ -305,9 +305,9 @@ 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); + gGL.begin(LLRender::TRIANGLES); { - gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); + gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 6); } gGL.end(); glyph_count = 0; @@ -338,9 +338,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons if (glyph_count >= GLYPH_BATCH_SIZE) { - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { - gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); + gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 6); } gGL.end(); @@ -376,9 +376,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons cur_render_y = cur_y; } - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { - gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); + gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 6); } gGL.end(); @@ -1227,7 +1227,7 @@ LLFontGL &LLFontGL::operator=(const LLFontGL &source) return *this; } -void LLFontGL::renderQuad(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const +void LLFontGL::renderTriangle(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const { S32 index = 0; @@ -1246,6 +1246,17 @@ void LLFontGL::renderQuad(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* c colors_out[index] = color; index++; + + vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mTop, 0.f); + uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); + colors_out[index] = color; + index++; + + vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 0.f); + uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom); + colors_out[index] = color; + index++; + vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 0.f); uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom); colors_out[index] = color; @@ -1265,7 +1276,7 @@ void LLFontGL::drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_ LLRectf screen_rect_offset = screen_rect; screen_rect_offset.translate((F32)(pass * BOLD_OFFSET), 0.f); - renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_offset, uv_rect, color, slant_offset); + renderTriangle(&vertex_out[glyph_count * 6], &uv_out[glyph_count * 6], &colors_out[glyph_count * 6], screen_rect_offset, uv_rect, color, slant_offset); glyph_count++; } } @@ -1296,10 +1307,10 @@ void LLFontGL::drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_ break; } - renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_offset, uv_rect, shadow_color, slant_offset); + renderTriangle(&vertex_out[glyph_count * 6], &uv_out[glyph_count * 6], &colors_out[glyph_count * 6], screen_rect_offset, uv_rect, shadow_color, slant_offset); glyph_count++; } - renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset); + renderTriangle(&vertex_out[glyph_count * 6], &uv_out[glyph_count * 6], &colors_out[glyph_count * 6], screen_rect, uv_rect, color, slant_offset); glyph_count++; } else if (shadow == DROP_SHADOW) @@ -1308,14 +1319,14 @@ void LLFontGL::drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_ shadow_color.mV[VALPHA] = U8(color.mV[VALPHA] * drop_shadow_strength); LLRectf screen_rect_shadow = screen_rect; screen_rect_shadow.translate(1.f, -1.f); - renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_shadow, uv_rect, shadow_color, slant_offset); + renderTriangle(&vertex_out[glyph_count * 6], &uv_out[glyph_count * 6], &colors_out[glyph_count * 6], screen_rect_shadow, uv_rect, shadow_color, slant_offset); glyph_count++; - renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset); + renderTriangle(&vertex_out[glyph_count * 6], &uv_out[glyph_count * 6], &colors_out[glyph_count * 6], screen_rect, uv_rect, color, slant_offset); glyph_count++; } else // normal rendering { - renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset); + renderTriangle(&vertex_out[glyph_count * 6], &uv_out[glyph_count * 6], &colors_out[glyph_count * 6], screen_rect, uv_rect, color, slant_offset); glyph_count++; } } diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index de7529a583..f04a77b49c 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -238,7 +238,7 @@ private: LLFontDescriptor mFontDescriptor; LLPointer mFontFreetype; - void renderQuad(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const; + void renderTriangle(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const; void drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const; // Registry holds all instantiated fonts. diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 16a8309a9a..f432b09107 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -803,7 +803,6 @@ void LLLightState::setSpotDirection(const LLVector3& direction) LLRender::LLRender() : mDirty(false), mCount(0), - mQuadCycle(0), mMode(LLRender::TRIANGLES), mCurrTextureUnitIndex(0) { @@ -1532,13 +1531,7 @@ void LLRender::begin(const GLuint& mode) { if (mode != mMode) { - if (mode == LLRender::QUADS) - { - mQuadCycle = 1; - } - - if (mMode == LLRender::QUADS || - mMode == LLRender::LINES || + if (mMode == LLRender::LINES || mMode == LLRender::TRIANGLES || mMode == LLRender::POINTS) { @@ -1561,8 +1554,7 @@ void LLRender::end() //IMM_ERRS << "GL begin and end called with no vertices specified." << LL_ENDL; } - if ((mMode != LLRender::QUADS && - mMode != LLRender::LINES && + if ((mMode != LLRender::LINES && mMode != LLRender::TRIANGLES && mMode != LLRender::POINTS) || mCount > 2048) @@ -1587,28 +1579,19 @@ void LLRender::flush() //store mCount in a local variable to avoid re-entrance (drawArrays may call flush) U32 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 (mMode == LLRender::TRIANGLES) + { + if (mCount%3 != 0) { - if (mCount%3 != 0) - { - count -= (mCount % 3); - LL_WARNS() << "Incomplete triangle requested." << LL_ENDL; - } + count -= (mCount % 3); + LL_WARNS() << "Incomplete triangle requested." << LL_ENDL; } + } - if (mMode == LLRender::LINES) + if (mMode == LLRender::LINES) + { + if (mCount%2 != 0) { - if (mCount%2 != 0) - { count -= (mCount % 2); LL_WARNS() << "Incomplete line requested." << LL_ENDL; } @@ -1758,16 +1741,7 @@ LLVertexBuffer* LLRender::genBuffer(U32 attribute_mask, S32 count) 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); - } + vb->drawArrays(mode, 0, count); } void LLRender::resetStriders(S32 count) @@ -1788,7 +1762,6 @@ void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) { case LLRender::POINTS: flush(); break; case LLRender::TRIANGLES: if (mCount%3==0) flush(); break; - case LLRender::QUADS: if(mCount%4 == 0) flush(); break; case LLRender::LINES: if (mCount%2 == 0) flush(); break; } } @@ -1809,25 +1782,6 @@ void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) mVerticesp[mCount] = vert; } - if (mMode == LLRender::QUADS && LLRender::sGLCoreProfile) - { - mQuadCycle++; - if (mQuadCycle == 4) - { //copy two vertices so fourth quad element will add a triangle - mQuadCycle = 0; - - mCount++; - mVerticesp[mCount] = mVerticesp[mCount-3]; - mColorsp[mCount] = mColorsp[mCount-3]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-3]; - - mCount++; - mVerticesp[mCount] = mVerticesp[mCount-2]; - mColorsp[mCount] = mColorsp[mCount-2]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-2]; - } - } - mCount++; mVerticesp[mCount] = mVerticesp[mCount-1]; mColorsp[mCount] = mColorsp[mCount-1]; @@ -1842,50 +1796,13 @@ void LLRender::vertexBatchPreTransformed(LLVector3* verts, S32 vert_count) return; } - if (sGLCoreProfile && mMode == LLRender::QUADS) - { //quads are deprecated, convert to triangle list - S32 i = 0; - - while (i < vert_count) - { - //read first three - mVerticesp[mCount++] = verts[i++]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - - mVerticesp[mCount++] = verts[i++]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - - mVerticesp[mCount++] = verts[i++]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - - //copy two - mVerticesp[mCount++] = verts[i-3]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - - mVerticesp[mCount++] = verts[i-1]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - - //copy last one - mVerticesp[mCount++] = verts[i++]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - } - } - else + for (S32 i = 0; i < vert_count; i++) { - for (S32 i = 0; i < vert_count; i++) - { - mVerticesp[mCount] = verts[i]; + mVerticesp[mCount] = verts[i]; - mCount++; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - } + mCount++; + mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; + mColorsp[mCount] = mColorsp[mCount-1]; } if( mCount > 0 ) // ND: Guard against crashes if mCount is zero, yes it can happen @@ -1900,50 +1817,13 @@ void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 v return; } - if (sGLCoreProfile && mMode == LLRender::QUADS) - { //quads are deprecated, convert to triangle list - S32 i = 0; - - while (i < vert_count) - { - //read first three - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount++] = uvs[i++]; - mColorsp[mCount] = mColorsp[mCount-1]; - - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount++] = uvs[i++]; - mColorsp[mCount] = mColorsp[mCount-1]; - - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount++] = uvs[i++]; - mColorsp[mCount] = mColorsp[mCount-1]; - - //copy last two - mVerticesp[mCount] = verts[i-3]; - mTexcoordsp[mCount++] = uvs[i-3]; - mColorsp[mCount] = mColorsp[mCount-1]; - - mVerticesp[mCount] = verts[i-1]; - mTexcoordsp[mCount++] = uvs[i-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - - //copy last one - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount++] = uvs[i++]; - mColorsp[mCount] = mColorsp[mCount-1]; - } - } - else + for (S32 i = 0; i < vert_count; i++) { - for (S32 i = 0; i < vert_count; i++) - { - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount] = uvs[i]; + mVerticesp[mCount] = verts[i]; + mTexcoordsp[mCount] = uvs[i]; - mCount++; - mColorsp[mCount] = mColorsp[mCount-1]; - } + mCount++; + mColorsp[mCount] = mColorsp[mCount-1]; } if (mCount > 0) @@ -1961,51 +1841,13 @@ void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, LLCol return; } - - if (sGLCoreProfile && mMode == LLRender::QUADS) - { //quads are deprecated, convert to triangle list - S32 i = 0; - - while (i < vert_count) - { - //read first three - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount] = uvs[i]; - mColorsp[mCount++] = colors[i++]; - - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount] = uvs[i]; - mColorsp[mCount++] = colors[i++]; - - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount] = uvs[i]; - mColorsp[mCount++] = colors[i++]; - - //copy last two - mVerticesp[mCount] = verts[i-3]; - mTexcoordsp[mCount] = uvs[i-3]; - mColorsp[mCount++] = colors[i-3]; - - mVerticesp[mCount] = verts[i-1]; - mTexcoordsp[mCount] = uvs[i-1]; - mColorsp[mCount++] = colors[i-1]; - - //copy last one - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount] = uvs[i]; - mColorsp[mCount++] = colors[i++]; - } - } - else + for (S32 i = 0; i < vert_count; i++) { - for (S32 i = 0; i < vert_count; i++) - { - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount] = uvs[i]; - mColorsp[mCount] = colors[i]; + mVerticesp[mCount] = verts[i]; + mTexcoordsp[mCount] = uvs[i]; + mColorsp[mCount] = colors[i]; - mCount++; - } + mCount++; } if (mCount > 0) diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 2645597b1a..2c1417cc26 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -319,7 +319,6 @@ public: POINTS, LINES, LINE_STRIP, - QUADS, LINE_LOOP, NUM_MODES }; @@ -508,7 +507,6 @@ private: LLColor4 mAmbientLightColor; bool mDirty; - U32 mQuadCycle; U32 mCount; U32 mMode; U32 mCurrTextureUnitIndex; diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index 27da64cce6..e488082c7e 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -175,50 +175,70 @@ void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &st LLColor4 end_color = start_color; end_color.mV[VALPHA] = 0.f; - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); // Right edge, CCW faces screen gGL.color4fv(start_color.mV); - gGL.vertex2i(right, top-lines); - gGL.vertex2i(right, bottom); + gGL.vertex2i(right, top - lines); + gGL.vertex2i(right, bottom); gGL.color4fv(end_color.mV); - gGL.vertex2i(right+lines, bottom); - gGL.vertex2i(right+lines, top-lines); + gGL.vertex2i(right + lines, bottom); + gGL.color4fv(start_color.mV); + gGL.vertex2i(right, top - lines); + gGL.color4fv(end_color.mV); + gGL.vertex2i(right + lines, bottom); + gGL.vertex2i(right + lines, top - lines); // Bottom edge, CCW faces screen gGL.color4fv(start_color.mV); - gGL.vertex2i(right, bottom); - gGL.vertex2i(left+lines, bottom); + gGL.vertex2i(right, bottom); + gGL.vertex2i(left + lines, bottom); gGL.color4fv(end_color.mV); - gGL.vertex2i(left+lines, bottom-lines); - gGL.vertex2i(right, bottom-lines); + gGL.vertex2i(left + lines, bottom - lines); + gGL.color4fv(start_color.mV); + gGL.vertex2i(right, bottom); + gGL.color4fv(end_color.mV); + gGL.vertex2i(left + lines, bottom - lines); + gGL.vertex2i(right, bottom - lines); // bottom left Corner gGL.color4fv(start_color.mV); - gGL.vertex2i(left+lines, bottom); + gGL.vertex2i(left + lines, bottom); gGL.color4fv(end_color.mV); - gGL.vertex2i(left, bottom); + gGL.vertex2i(left, bottom); // make the bottom left corner not sharp - gGL.vertex2i(left+1, bottom-lines+1); - gGL.vertex2i(left+lines, bottom-lines); + gGL.vertex2i(left + 1, bottom - lines + 1); + gGL.color4fv(start_color.mV); + gGL.vertex2i(left + lines, bottom); + gGL.color4fv(end_color.mV); + gGL.vertex2i(left + 1, bottom - lines + 1); + gGL.vertex2i(left + lines, bottom - lines); // bottom right corner gGL.color4fv(start_color.mV); - gGL.vertex2i(right, bottom); + gGL.vertex2i(right, bottom); gGL.color4fv(end_color.mV); - gGL.vertex2i(right, bottom-lines); + gGL.vertex2i(right, bottom - lines); // make the rightmost corner not sharp - gGL.vertex2i(right+lines-1, bottom-lines+1); - gGL.vertex2i(right+lines, bottom); + gGL.vertex2i(right + lines - 1, bottom - lines + 1); + gGL.color4fv(start_color.mV); + gGL.vertex2i(right, bottom); + gGL.color4fv(end_color.mV); + gGL.vertex2i(right + lines - 1, bottom - lines + 1); + gGL.vertex2i(right + lines, bottom); // top right corner gGL.color4fv(start_color.mV); - gGL.vertex2i( right, top-lines ); + gGL.vertex2i(right, top - lines); gGL.color4fv(end_color.mV); - gGL.vertex2i( right+lines, top-lines ); + gGL.vertex2i(right + lines, top - lines); // make the corner not sharp - gGL.vertex2i( right+lines-1, top-1 ); - gGL.vertex2i( right, top ); + gGL.vertex2i(right + lines - 1, top - 1); + gGL.color4fv(start_color.mV); + gGL.vertex2i(right, top - lines); + gGL.color4fv(end_color.mV); + gGL.vertex2i(right + lines - 1, top - 1); + gGL.vertex2i(right, top); gGL.end(); stop_glerror(); diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 0be799db9d..6f4828397a 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -633,15 +633,7 @@ void LLVertexBufferData::draw() gGL.loadMatrix(glm::value_ptr(mTexture0)); mVB->setBuffer(); - - if (mMode == LLRender::QUADS && LLRender::sGLCoreProfile) - { - mVB->drawArrays(LLRender::TRIANGLES, 0, mCount); - } - else - { - mVB->drawArrays(mMode, 0, mCount); - } + mVB->drawArrays(mMode, 0, mCount); gGL.popMatrix(); gGL.matrixMode(LLRender::MM_PROJECTION); @@ -714,7 +706,6 @@ const U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] = GL_POINTS, GL_LINES, GL_LINE_STRIP, - GL_QUADS, GL_LINE_LOOP, }; -- cgit v1.2.3 From f037cde7f4d5d55dc0a71eb867f5b2bfcaf5631f Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 11 Sep 2024 12:29:18 -0400 Subject: Make Develop->Render Tests->Frame Profile dump JSON to a file too. Make `LLGLSLShader::finishProfile()` accept a string pathname instead of a bool and, in addition to logging statistics to the viewer log, output statistics to that file as JSON. The calls that used to pass `emit_report=false` now pass `report_name=std::string()`. Make llviewerdisplay.cpp's `display()` function synthesize a profile filename in the viewer's logs directory, and pass that filename to `LLGLSLShader::finishProfile()`. (cherry picked from commit d5712689d36a1ee1af32242706901fde7229b08d) --- indra/llrender/llglslshader.cpp | 120 +++++++++++++++++++++++++--------------- indra/llrender/llglslshader.h | 5 +- 2 files changed, 79 insertions(+), 46 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index a157bfee21..bb734971d5 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -41,6 +41,8 @@ #include "OpenGL/OpenGL.h" #endif +#include + // Print-print list of shader included source files that are linked together via glAttachShader() // i.e. On macOS / OSX the AMD GLSL linker will display an error if a varying is left in an undefined state. #define DEBUG_SHADER_INCLUDES 0 @@ -101,9 +103,9 @@ void LLGLSLShader::initProfile() sTotalSamplesDrawn = 0; sTotalBinds = 0; - for (std::set::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) + for (auto ptr : sInstances) { - (*iter)->clearStats(); + ptr->clearStats(); } } @@ -117,48 +119,71 @@ struct LLGLSLShaderCompareTimeElapsed }; //static -void LLGLSLShader::finishProfile(bool emit_report) +void LLGLSLShader::finishProfile(const std::string& report_name) { sProfileEnabled = false; - if (emit_report) + if (! report_name.empty()) { - std::vector sorted; - - for (std::set::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) - { - sorted.push_back(*iter); - } - + std::vector sorted(sInstances.begin(), sInstances.end()); std::sort(sorted.begin(), sorted.end(), LLGLSLShaderCompareTimeElapsed()); + boost::json::object stats; + auto shadersit = stats.emplace("shaders", boost::json::array_kind).first; + auto& shaders = shadersit->value().as_array(); bool unbound = false; - for (std::vector::iterator iter = sorted.begin(); iter != sorted.end(); ++iter) + for (auto ptr : sorted) { - (*iter)->dumpStats(); - if ((*iter)->mBinds == 0) + if (ptr->mBinds == 0) { unbound = true; } + else + { + auto& shaderit = shaders.emplace_back(boost::json::object_kind); + ptr->dumpStats(shaderit.as_object()); + } } + constexpr float mega = 1'000'000.f; + float totalTimeMs = sTotalTimeElapsed / mega; LL_INFOS() << "-----------------------------------" << LL_ENDL; - LL_INFOS() << "Total rendering time: " << llformat("%.4f ms", sTotalTimeElapsed / 1000000.f) << LL_ENDL; - LL_INFOS() << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn / 1000000.f) << LL_ENDL; - LL_INFOS() << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn / 1000000.f) << LL_ENDL; + LL_INFOS() << "Total rendering time: " << llformat("%.4f ms", totalTimeMs) << LL_ENDL; + LL_INFOS() << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn / mega) << LL_ENDL; + LL_INFOS() << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn / mega) << LL_ENDL; LL_INFOS() << "-----------------------------------" << LL_ENDL; - + auto totalsit = stats.emplace("totals", boost::json::object_kind).first; + auto& totals = totalsit->value().as_object(); + totals.emplace("time", totalTimeMs / 1000.0); + totals.emplace("binds", sTotalBinds); + totals.emplace("samples", sTotalSamplesDrawn); + totals.emplace("triangles", sTotalTrianglesDrawn); + + auto unusedit = stats.emplace("unused", boost::json::array_kind).first; + auto& unused = unusedit->value().as_array(); if (unbound) { LL_INFOS() << "The following shaders were unused: " << LL_ENDL; - for (std::vector::iterator iter = sorted.begin(); iter != sorted.end(); ++iter) + for (auto ptr : sorted) { - if ((*iter)->mBinds == 0) + if (ptr->mBinds == 0) { - LL_INFOS() << (*iter)->mName << LL_ENDL; + LL_INFOS() << ptr->mName << LL_ENDL; + unused.emplace_back(ptr->mName); } } } + + std::ofstream outf(report_name); + if (! outf) + { + LL_WARNS() << "Couldn't write to " << std::quoted(report_name) << LL_ENDL; + } + else + { + outf << stats; + LL_INFOS() << "(also dumped to " << std::quoted(report_name) << ")" << LL_ENDL; + } } } @@ -170,36 +195,43 @@ void LLGLSLShader::clearStats() mBinds = 0; } -void LLGLSLShader::dumpStats() +void LLGLSLShader::dumpStats(boost::json::object& stats) { - if (mBinds > 0) + stats.emplace("name", mName); + auto filesit = stats.emplace("files", boost::json::array_kind).first; + auto& files = filesit->value().as_array(); + LL_INFOS() << "=============================================" << LL_ENDL; + LL_INFOS() << mName << LL_ENDL; + for (U32 i = 0; i < mShaderFiles.size(); ++i) { - LL_INFOS() << "=============================================" << LL_ENDL; - LL_INFOS() << mName << LL_ENDL; - for (U32 i = 0; i < mShaderFiles.size(); ++i) - { - LL_INFOS() << mShaderFiles[i].first << LL_ENDL; - } - LL_INFOS() << "=============================================" << LL_ENDL; + LL_INFOS() << mShaderFiles[i].first << LL_ENDL; + files.emplace_back(mShaderFiles[i].first); + } + LL_INFOS() << "=============================================" << LL_ENDL; - F32 ms = mTimeElapsed / 1000000.f; - F32 seconds = ms / 1000.f; + constexpr float mega = 1'000'000.f; + constexpr double giga = 1'000'000'000.0; + F32 ms = mTimeElapsed / mega; + F32 seconds = ms / 1000.f; - F32 pct_tris = (F32)mTrianglesDrawn / (F32)sTotalTrianglesDrawn * 100.f; - F32 tris_sec = (F32)(mTrianglesDrawn / 1000000.0); - tris_sec /= seconds; + F32 pct_tris = (F32)mTrianglesDrawn / (F32)sTotalTrianglesDrawn * 100.f; + F32 tris_sec = (F32)(mTrianglesDrawn / mega); + tris_sec /= seconds; - F32 pct_samples = (F32)((F64)mSamplesDrawn / (F64)sTotalSamplesDrawn) * 100.f; - F32 samples_sec = (F32)(mSamplesDrawn / 1000000000.0); - samples_sec /= seconds; + F32 pct_samples = (F32)((F64)mSamplesDrawn / (F64)sTotalSamplesDrawn) * 100.f; + F32 samples_sec = (F32)(mSamplesDrawn / giga); + samples_sec /= seconds; - F32 pct_binds = (F32)mBinds / (F32)sTotalBinds * 100.f; + F32 pct_binds = (F32)mBinds / (F32)sTotalBinds * 100.f; - LL_INFOS() << "Triangles Drawn: " << mTrianglesDrawn << " " << llformat("(%.2f pct of total, %.3f million/sec)", pct_tris, tris_sec) << LL_ENDL; - LL_INFOS() << "Binds: " << mBinds << " " << llformat("(%.2f pct of total)", pct_binds) << LL_ENDL; - LL_INFOS() << "SamplesDrawn: " << mSamplesDrawn << " " << llformat("(%.2f pct of total, %.3f billion/sec)", pct_samples, samples_sec) << LL_ENDL; - LL_INFOS() << "Time Elapsed: " << mTimeElapsed << " " << llformat("(%.2f pct of total, %.5f ms)\n", (F32)((F64)mTimeElapsed / (F64)sTotalTimeElapsed) * 100.f, ms) << LL_ENDL; - } + LL_INFOS() << "Triangles Drawn: " << mTrianglesDrawn << " " << llformat("(%.2f pct of total, %.3f million/sec)", pct_tris, tris_sec) << LL_ENDL; + LL_INFOS() << "Binds: " << mBinds << " " << llformat("(%.2f pct of total)", pct_binds) << LL_ENDL; + LL_INFOS() << "SamplesDrawn: " << mSamplesDrawn << " " << llformat("(%.2f pct of total, %.3f billion/sec)", pct_samples, samples_sec) << LL_ENDL; + LL_INFOS() << "Time Elapsed: " << mTimeElapsed << " " << llformat("(%.2f pct of total, %.5f ms)\n", (F32)((F64)mTimeElapsed / (F64)sTotalTimeElapsed) * 100.f, ms) << LL_ENDL; + stats.emplace("time", seconds); + stats.emplace("binds", mBinds); + stats.emplace("samples", mSamplesDrawn); + stats.emplace("triangles", mTrianglesDrawn); } //static diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 27c8f0b7d0..efcbaf42e8 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -30,6 +30,7 @@ #include "llgl.h" #include "llrender.h" #include "llstaticstringtable.h" +#include #include class LLShaderFeatures @@ -169,14 +170,14 @@ public: static U32 sMaxGLTFNodes; static void initProfile(); - static void finishProfile(bool emit_report = true); + static void finishProfile(const std::string& report_name={}); static void startProfile(); static void stopProfile(); void unload(); void clearStats(); - void dumpStats(); + void dumpStats(boost::json::object& stats); // place query objects for profiling if profiling is enabled // if for_runtime is true, will place timer query only whether or not profiling is enabled -- cgit v1.2.3 From a3d6544be07e3cd0bb7e4cb78564a0d6077fd910 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 12 Sep 2024 09:12:33 -0400 Subject: Give `LLGLSLShader::finishProfile()` a static default string param. `finishProfile()` is called at least once within a `__try` block. If we default its `report_name` parameter to a temporary `std::string`, that temporary must be destroyed when the stack is unwound, which `__try` forbids. (cherry picked from commit c6e6f44f50b4de391000c5b9f781a2f0a5024e76) --- indra/llrender/llglslshader.cpp | 1 + indra/llrender/llglslshader.h | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index bb734971d5..56f1533708 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -65,6 +65,7 @@ U64 LLGLSLShader::sTotalTimeElapsed = 0; U32 LLGLSLShader::sTotalTrianglesDrawn = 0; U64 LLGLSLShader::sTotalSamplesDrawn = 0; U32 LLGLSLShader::sTotalBinds = 0; +std::string LLGLSLShader::sDefaultReportName; //UI shader -- declared here so llui_libtest will link properly LLGLSLShader gUIProgram; diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index efcbaf42e8..a9b9bfafa8 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -170,7 +170,7 @@ public: static U32 sMaxGLTFNodes; static void initProfile(); - static void finishProfile(const std::string& report_name={}); + static void finishProfile(const std::string& report_name=sDefaultReportName); static void startProfile(); static void stopProfile(); @@ -364,6 +364,11 @@ public: private: void unloadInternal(); + // This must be static because finishProfile() is called at least once + // within a __try block. If we default its report_name parameter to a + // temporary std::string, that temporary must be destroyed when the stack + // is unwound, which __try forbids. + static std::string sDefaultReportName; }; //UI shader (declared here so llui_libtest will link properly) -- cgit v1.2.3 From 6d842ac0af814a088c56f437dc885e4ce58b61a8 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 18 Sep 2024 17:11:03 +0300 Subject: Expose LLVector4a in LLRender Avoid using a bunch of allocators. Make sure we use LLVector4a's SSE logic instead of LLVector3's. Some minor optimizations. --- indra/llrender/llfontgl.cpp | 30 +++++++++++++++--------------- indra/llrender/llfontgl.h | 4 ++-- indra/llrender/llrender.cpp | 16 ++++++++-------- indra/llrender/llrender.h | 8 ++++---- indra/llrender/llrender2dutils.cpp | 10 +++------- 5 files changed, 32 insertions(+), 36 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 21593b7cb4..94daba0817 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -271,7 +271,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons const LLFontGlyphInfo* next_glyph = NULL; static constexpr S32 GLYPH_BATCH_SIZE = 30; - static thread_local LLVector3 vertices[GLYPH_BATCH_SIZE * 6]; + static thread_local LLVector4a vertices[GLYPH_BATCH_SIZE * 6]; static thread_local LLVector2 uvs[GLYPH_BATCH_SIZE * 6]; static thread_local LLColor4U colors[GLYPH_BATCH_SIZE * 6]; @@ -1227,42 +1227,42 @@ LLFontGL &LLFontGL::operator=(const LLFontGL &source) return *this; } -void LLFontGL::renderTriangle(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const +void LLFontGL::renderTriangle(LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const { S32 index = 0; - vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mTop, 0.f); - uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); + vertex_out[index].set(screen_rect.mRight, screen_rect.mTop, 0.f); + uv_out[index].set(uv_rect.mRight, uv_rect.mTop); colors_out[index] = color; index++; - vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 0.f); - uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop); + vertex_out[index].set(screen_rect.mLeft, screen_rect.mTop, 0.f); + uv_out[index].set(uv_rect.mLeft, uv_rect.mTop); colors_out[index] = color; index++; - vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 0.f); - uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom); + vertex_out[index].set(screen_rect.mLeft, screen_rect.mBottom, 0.f); + uv_out[index].set(uv_rect.mLeft, uv_rect.mBottom); colors_out[index] = color; index++; - vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mTop, 0.f); - uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); + vertex_out[index].set(screen_rect.mRight, screen_rect.mTop, 0.f); + uv_out[index].set(uv_rect.mRight, uv_rect.mTop); colors_out[index] = color; index++; - vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 0.f); - uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom); + vertex_out[index].set(screen_rect.mLeft, screen_rect.mBottom, 0.f); + uv_out[index].set(uv_rect.mLeft, uv_rect.mBottom); colors_out[index] = color; index++; - vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 0.f); - uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom); + vertex_out[index].set(screen_rect.mRight, screen_rect.mBottom, 0.f); + uv_out[index].set(uv_rect.mRight, uv_rect.mBottom); colors_out[index] = color; } -void LLFontGL::drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const +void LLFontGL::drawGlyph(S32& glyph_count, LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const { F32 slant_offset; slant_offset = ((style & ITALIC) ? ( -mFontFreetype->getAscenderHeight() * 0.2f) : 0.f); diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index f04a77b49c..4bb6c55c65 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -238,8 +238,8 @@ private: LLFontDescriptor mFontDescriptor; LLPointer mFontFreetype; - void renderTriangle(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const; - void drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const; + void renderTriangle(LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const; + void drawGlyph(S32& glyph_count, LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const; // Registry holds all instantiated fonts. static LLFontRegistry* sFontRegistry; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index f432b09107..c8a9fb4893 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1298,7 +1298,7 @@ void LLRender::pushUIMatrix() { if (mUIOffset.empty()) { - mUIOffset.push_back(LLVector3(0,0,0)); + mUIOffset.emplace_back(0.f,0.f,0.f); } else { @@ -1307,7 +1307,7 @@ void LLRender::pushUIMatrix() if (mUIScale.empty()) { - mUIScale.push_back(LLVector3(1,1,1)); + mUIScale.emplace_back(1.f,1.f,1.f); } else { @@ -1718,7 +1718,7 @@ LLVertexBuffer* LLRender::genBuffer(U32 attribute_mask, S32 count) vb->setBuffer(); - vb->setPositionData((LLVector4a*)mVerticesp.get()); + vb->setPositionData(mVerticesp.get()); if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0) { @@ -1774,12 +1774,12 @@ void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) if (mUIOffset.empty()) { - mVerticesp[mCount] = LLVector3(x,y,z); + mVerticesp[mCount].set(x,y,z); } else { LLVector3 vert = (LLVector3(x,y,z)+mUIOffset.back()).scaledVec(mUIScale.back()); - mVerticesp[mCount] = vert; + mVerticesp[mCount].set(vert.mV[VX], vert.mV[VY], vert.mV[VZ]); } mCount++; @@ -1788,7 +1788,7 @@ void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; } -void LLRender::vertexBatchPreTransformed(LLVector3* verts, S32 vert_count) +void LLRender::vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count) { if (mCount + vert_count > 4094) { @@ -1809,7 +1809,7 @@ void LLRender::vertexBatchPreTransformed(LLVector3* verts, S32 vert_count) mVerticesp[mCount] = mVerticesp[mCount-1]; } -void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count) +void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count) { if (mCount + vert_count > 4094) { @@ -1833,7 +1833,7 @@ void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 v } } -void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, LLColor4U* colors, S32 vert_count) +void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLColor4U* colors, S32 vert_count) { if (mCount + vert_count > 4094) { diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 2c1417cc26..fc7c5ccc18 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -449,9 +449,9 @@ public: void diffuseColor4ubv(const U8* c); void diffuseColor4ub(U8 r, U8 g, U8 b, U8 a); - void vertexBatchPreTransformed(LLVector3* verts, S32 vert_count); - void vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count); - void vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, LLColor4U*, S32 vert_count); + void vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count); + void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count); + void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLColor4U*, S32 vert_count); void setColorMask(bool writeColor, bool writeAlpha); void setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha); @@ -513,7 +513,7 @@ private: bool mCurrColorMask[4]; LLPointer mBuffer; - LLStrider mVerticesp; + LLStrider mVerticesp; LLStrider mTexcoordsp; LLStrider mColorsp; std::array mTexUnits; diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index e488082c7e..20ad0275bd 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -446,15 +446,13 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex ui_translation.mV[VX] + width * ui_scale.mV[VX], ui_translation.mV[VY]); - LLGLSUIDefault gls_ui; - gGL.getTexUnit(0)->bind(image, true); gGL.color4fv(color.mV); constexpr S32 NUM_VERTICES = 9 * 2 * 3; // 9 quads, 2 triangles per quad, 3 vertices per triangle static thread_local LLVector2 uv[NUM_VERTICES]; - static thread_local LLVector3 pos[NUM_VERTICES]; + static thread_local LLVector4a pos[NUM_VERTICES]; S32 index = 0; @@ -719,8 +717,6 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre return; } - LLGLSUIDefault gls_ui; - if(image != NULL) { gGL.getTexUnit(0)->bind(image, true); @@ -735,8 +731,8 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre if (degrees == 0.f) { constexpr S32 NUM_VERTICES = 2 * 3; - static thread_local LLVector2 uv[NUM_VERTICES]; - static thread_local LLVector3 pos[NUM_VERTICES]; + static thread_local LLVector2 uv[NUM_VERTICES +1]; + static thread_local LLVector4a pos[NUM_VERTICES +1]; gGL.begin(LLRender::TRIANGLES); { -- cgit v1.2.3 From 8c40e6f0a9e211ec22331385dc66b5ff5233859c Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 19 Sep 2024 11:46:08 -0400 Subject: Reapply commit f4b6563 -- cherry-picking lost parts of it?! --- indra/llrender/llglslshader.cpp | 21 ++++----------------- indra/llrender/llglslshader.h | 10 +++++----- 2 files changed, 9 insertions(+), 22 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 56f1533708..6ba5463acd 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -41,8 +41,6 @@ #include "OpenGL/OpenGL.h" #endif -#include - // Print-print list of shader included source files that are linked together via glAttachShader() // i.e. On macOS / OSX the AMD GLSL linker will display an error if a varying is left in an undefined state. #define DEBUG_SHADER_INCLUDES 0 @@ -65,7 +63,7 @@ U64 LLGLSLShader::sTotalTimeElapsed = 0; U32 LLGLSLShader::sTotalTrianglesDrawn = 0; U64 LLGLSLShader::sTotalSamplesDrawn = 0; U32 LLGLSLShader::sTotalBinds = 0; -std::string LLGLSLShader::sDefaultReportName; +boost::json::value LLGLSLShader::sDefaultStats; //UI shader -- declared here so llui_libtest will link properly LLGLSLShader gUIProgram; @@ -120,16 +118,16 @@ struct LLGLSLShaderCompareTimeElapsed }; //static -void LLGLSLShader::finishProfile(const std::string& report_name) +void LLGLSLShader::finishProfile(boost::json::value& statsv) { sProfileEnabled = false; - if (! report_name.empty()) + if (! statsv.is_null()) { std::vector sorted(sInstances.begin(), sInstances.end()); std::sort(sorted.begin(), sorted.end(), LLGLSLShaderCompareTimeElapsed()); - boost::json::object stats; + auto& stats = statsv.as_object(); auto shadersit = stats.emplace("shaders", boost::json::array_kind).first; auto& shaders = shadersit->value().as_array(); bool unbound = false; @@ -174,17 +172,6 @@ void LLGLSLShader::finishProfile(const std::string& report_name) } } } - - std::ofstream outf(report_name); - if (! outf) - { - LL_WARNS() << "Couldn't write to " << std::quoted(report_name) << LL_ENDL; - } - else - { - outf << stats; - LL_INFOS() << "(also dumped to " << std::quoted(report_name) << ")" << LL_ENDL; - } } } diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index a9b9bfafa8..2d669c70a9 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -170,7 +170,7 @@ public: static U32 sMaxGLTFNodes; static void initProfile(); - static void finishProfile(const std::string& report_name=sDefaultReportName); + static void finishProfile(boost::json::value& stats=sDefaultStats); static void startProfile(); static void stopProfile(); @@ -365,10 +365,10 @@ public: private: void unloadInternal(); // This must be static because finishProfile() is called at least once - // within a __try block. If we default its report_name parameter to a - // temporary std::string, that temporary must be destroyed when the stack - // is unwound, which __try forbids. - static std::string sDefaultReportName; + // within a __try block. If we default its stats parameter to a temporary + // json::value, that temporary must be destroyed when the stack is + // unwound, which __try forbids. + static boost::json::value sDefaultStats; }; //UI shader (declared here so llui_libtest will link properly) -- 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 +++++++ indra/llrender/llfontvertexbuffer.h | 4 ++++ 2 files changed, 11 insertions(+) (limited to 'indra/llrender') 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, diff --git a/indra/llrender/llfontvertexbuffer.h b/indra/llrender/llfontvertexbuffer.h index 67cf2ca13c..59cb536b74 100644 --- a/indra/llrender/llfontvertexbuffer.h +++ b/indra/llrender/llfontvertexbuffer.h @@ -78,6 +78,8 @@ public: F32* right_x = NULL, bool use_ellipses = false, bool use_color = true); + + static void enableBufferCollection(bool enable) { sEnableBufferCollection = enable; } private: void genBuffers(const LLFontGL* fontp, @@ -114,6 +116,8 @@ private: F32 mLastScaleX = 1.f; F32 mLastScaleY = 1.f; LLCoordGL mLastOrigin; + + static bool sEnableBufferCollection; }; #endif -- cgit v1.2.3 From e74b48e67842c5c745f9ab0be2e33d7d077001e3 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 26 Sep 2024 22:03:45 +0300 Subject: viewer#2709 Fix loose triangle --- indra/llrender/llrender2dutils.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index 20ad0275bd..c3d5da0914 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -1712,10 +1712,10 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV); gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); - gGL.vertex3fv((center_draw_rect.mLeft* width_vec + center_draw_rect.mTop * height_vec).mV); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); - gGL.vertex3fv((center_draw_rect.mRight* width_vec + center_draw_rect.mTop * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight* width_vec + height_vec).mV); gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); -- cgit v1.2.3