From 8d0efb54db96c87a2adb4a824998870ff397846e Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Thu, 27 Jan 2022 12:57:30 -0700 Subject: SL-16418 rename media tex image per-update to avoid contention stall --- indra/llrender/llimagegl.cpp | 66 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 11 deletions(-) (limited to 'indra/llrender/llimagegl.cpp') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 1e9b9f642e..4b4f071171 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1215,9 +1215,8 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE) { //GL_ALPHA is deprecated, convert to RGBA use_scratch = true; - scratch = new U32[width * height]; - U32 pixel_count = (U32)(width * height); + scratch = new U32[pixel_count]; for (U32 i = 0; i < pixel_count; i++) { U8* pix = (U8*)&scratch[i]; @@ -1232,9 +1231,8 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE) { //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA use_scratch = true; - scratch = new U32[width * height]; - U32 pixel_count = (U32)(width * height); + scratch = new U32[pixel_count]; for (U32 i = 0; i < pixel_count; i++) { U8 lum = ((U8*)pixels)[i * 2 + 0]; @@ -1252,9 +1250,8 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE) { //GL_LUMINANCE_ALPHA is deprecated, convert to RGB use_scratch = true; - scratch = new U32[width * height]; - U32 pixel_count = (U32)(width * height); + scratch = new U32[pixel_count]; for (U32 i = 0; i < pixel_count; i++) { U8 lum = ((U8*)pixels)[i]; @@ -1314,10 +1311,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt } stop_glerror(); - if (use_scratch) - { - delete[] scratch; - } + if (scratch) delete[] scratch; } //create an empty GL texture: just create a texture name @@ -1471,7 +1465,49 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S return createGLTexture(discard_level, rawdata, FALSE, usename); } -BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) +// Create a new GL name and allocate tex storage (unitialized) for it +// Used to break resource contention stall in background media tex updates +void LLImageGL::allocNewTexName() +{ + LL_PROFILE_ZONE_SCOPED; + if (on_main_thread()) return; // Should only be called on bg update thread + if (!mGLTextureCreated) return; + if (0 != mNewTexName) return; // only 1 rename in flight at a time + + generateTextures(1, &mNewTexName); // create new GL name + + mHasMipMaps = false; // Media textures aren't mipped + mMipLevels = 0; + // Set state to match current + gGL.getTexUnit(0)->bind(this, false, false, mNewTexName); + glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel); + glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_WIDTH, mWidth); + glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_HEIGHT, mHeight); + gGL.getTexUnit(0)->setHasMipMaps(mHasMipMaps); + gGL.getTexUnit(0)->setTextureAddressMode(mAddressMode); + gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption); + + setManualImage(mTarget, 0, mFormatInternal, mWidth, mHeight, mFormatPrimary, mFormatType, + (GLvoid *) nullptr, mAllowCompression); + + gGL.getTexUnit(0)->unbind(mBindTarget); + + mLastBindTime = sLastFrameTime; +} + +// Delete no-longer-needed GL tex name (on main thread) +void LLImageGL::swapTexName() +{ + if (mNewTexName) + { + deleteTextures(1, &mTexName); + mTexName = mNewTexName; + mNewTexName = 0; + } +} + +BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips /* = FALSE */, S32 usename /* = 0 */) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; checkActiveThread(); @@ -1715,6 +1751,14 @@ void LLImageGL::destroyGLTexture() mTexName = 0; mGLTextureCreated = FALSE ; } + + // clean up any in-flight name change + if (0 != mNewTexName) + { + // Memory is transient, not tracked by sGlobalTextuerMemory + LLImageGL::deleteTextures(1, &mNewTexName); + mNewTexName = 0; + } } //force to invalidate the gl texture, most likely a sculpty texture -- cgit v1.2.3 From fdc4a81b578f26ce573d6b60760c8235312a6372 Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Tue, 1 Feb 2022 15:49:32 -0700 Subject: Revert "Merged in euclid-16418 (pull request #846)" This reverts commit 40fe5277e1390c975d9a3184ff8fc46d69dfb450, reversing changes made to af830e5fc5840194be95140f644a27011b9b7e06. --- indra/llrender/llimagegl.cpp | 66 ++++++++------------------------------------ 1 file changed, 11 insertions(+), 55 deletions(-) (limited to 'indra/llrender/llimagegl.cpp') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 4b4f071171..1e9b9f642e 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1215,8 +1215,9 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE) { //GL_ALPHA is deprecated, convert to RGBA use_scratch = true; + scratch = new U32[width * height]; + U32 pixel_count = (U32)(width * height); - scratch = new U32[pixel_count]; for (U32 i = 0; i < pixel_count; i++) { U8* pix = (U8*)&scratch[i]; @@ -1231,8 +1232,9 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE) { //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA use_scratch = true; + scratch = new U32[width * height]; + U32 pixel_count = (U32)(width * height); - scratch = new U32[pixel_count]; for (U32 i = 0; i < pixel_count; i++) { U8 lum = ((U8*)pixels)[i * 2 + 0]; @@ -1250,8 +1252,9 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE) { //GL_LUMINANCE_ALPHA is deprecated, convert to RGB use_scratch = true; + scratch = new U32[width * height]; + U32 pixel_count = (U32)(width * height); - scratch = new U32[pixel_count]; for (U32 i = 0; i < pixel_count; i++) { U8 lum = ((U8*)pixels)[i]; @@ -1311,7 +1314,10 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt } stop_glerror(); - if (scratch) delete[] scratch; + if (use_scratch) + { + delete[] scratch; + } } //create an empty GL texture: just create a texture name @@ -1465,49 +1471,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S return createGLTexture(discard_level, rawdata, FALSE, usename); } -// Create a new GL name and allocate tex storage (unitialized) for it -// Used to break resource contention stall in background media tex updates -void LLImageGL::allocNewTexName() -{ - LL_PROFILE_ZONE_SCOPED; - if (on_main_thread()) return; // Should only be called on bg update thread - if (!mGLTextureCreated) return; - if (0 != mNewTexName) return; // only 1 rename in flight at a time - - generateTextures(1, &mNewTexName); // create new GL name - - mHasMipMaps = false; // Media textures aren't mipped - mMipLevels = 0; - // Set state to match current - gGL.getTexUnit(0)->bind(this, false, false, mNewTexName); - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel); - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_WIDTH, mWidth); - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_HEIGHT, mHeight); - gGL.getTexUnit(0)->setHasMipMaps(mHasMipMaps); - gGL.getTexUnit(0)->setTextureAddressMode(mAddressMode); - gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption); - - setManualImage(mTarget, 0, mFormatInternal, mWidth, mHeight, mFormatPrimary, mFormatType, - (GLvoid *) nullptr, mAllowCompression); - - gGL.getTexUnit(0)->unbind(mBindTarget); - - mLastBindTime = sLastFrameTime; -} - -// Delete no-longer-needed GL tex name (on main thread) -void LLImageGL::swapTexName() -{ - if (mNewTexName) - { - deleteTextures(1, &mTexName); - mTexName = mNewTexName; - mNewTexName = 0; - } -} - -BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips /* = FALSE */, S32 usename /* = 0 */) +BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; checkActiveThread(); @@ -1751,14 +1715,6 @@ void LLImageGL::destroyGLTexture() mTexName = 0; mGLTextureCreated = FALSE ; } - - // clean up any in-flight name change - if (0 != mNewTexName) - { - // Memory is transient, not tracked by sGlobalTextuerMemory - LLImageGL::deleteTextures(1, &mNewTexName); - mNewTexName = 0; - } } //force to invalidate the gl texture, most likely a sculpty texture -- cgit v1.2.3 From f47730b92c309092d0a5a95e2d49d7ad53230a97 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 14 Feb 2022 18:07:24 +0000 Subject: SL-16418 Media texture update stall fix. Make media texture updates use LLImageGL thread to update, fix AMD sync issue on ImageGL thread and install debug callbacks on LLImageGL thread when debug gl enabled. --- indra/llrender/llimagegl.cpp | 139 +++++++++++++++++++++++++++++-------------- 1 file changed, 94 insertions(+), 45 deletions(-) (limited to 'indra/llrender/llimagegl.cpp') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 1e9b9f642e..694c4a7b06 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -550,7 +550,7 @@ bool LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_leve if (width != mWidth || height != mHeight || ncomponents != mComponents) { // Check if dimensions are a power of two! - if (!checkSize(width,height)) + if (!checkSize(width, height)) { LL_WARNS() << llformat("Texture has non power of two dimension: %dx%d",width,height) << LL_ENDL; return false; @@ -674,7 +674,7 @@ void LLImageGL::setImage(const LLImageRaw* imageraw) setImage(rawdata, FALSE); } -BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips, S32 usename) +BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips /* = FALSE */, S32 usename /* = 0 */) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; bool is_compressed = false; @@ -709,8 +709,14 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips, S32 usename) gGL.getTexUnit(0)->bind(this, false, false, usename); - - if (mUseMipMaps) + if (data_in == nullptr) + { + S32 w = getWidth(); + S32 h = getHeight(); + LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h, + mFormatPrimary, mFormatType, (GLvoid*)data_in, mAllowCompression); + } + else if (mUseMipMaps) { if (data_hasmips) { @@ -1069,14 +1075,14 @@ void LLImageGL::postAddToAtlas() stop_glerror(); } -BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update) +BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update /* = FALSE */, bool use_new_name /* = false */) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if (!width || !height) { return TRUE; } - if (mTexName == 0) + if (0 == (use_new_name ? mNewTexName : mTexName)) { // *TODO: Re-enable warning? Ran into thread locking issues? DK 2011-02-18 //LL_WARNS() << "Setting subimage on image without GL texture" << LL_ENDL; @@ -1092,7 +1098,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 // HACK: allow the caller to explicitly force the fast path (i.e. using glTexSubImage2D here instead of calling setImage) even when updating the full texture. if (!force_fast_update && x_pos == 0 && y_pos == 0 && width == getWidth() && height == getHeight() && data_width == width && data_height == height) { - setImage(datap, FALSE); + setImage(datap, FALSE, use_new_name ? mNewTexName : mTexName); } else { @@ -1144,12 +1150,11 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 datap += (y_pos * data_width + x_pos) * getComponents(); // Update the GL texture - BOOL res = gGL.getTexUnit(0)->bindManual(mBindTarget, mTexName); + BOOL res = gGL.getTexUnit(0)->bindManual(mBindTarget, use_new_name ? mNewTexName : mTexName); if (!res) LL_ERRS() << "LLImageGL::setSubImage(): bindTexture failed" << LL_ENDL; stop_glerror(); - glTexSubImage2D(mTarget, 0, x_pos, y_pos, - width, height, mFormatPrimary, mFormatType, datap); + glTexSubImage2D(mTarget, 0, x_pos, y_pos, width, height, mFormatPrimary, mFormatType, datap); gGL.getTexUnit(0)->disable(); stop_glerror(); @@ -1166,10 +1171,10 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 return TRUE; } -BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update) +BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update /* = FALSE */, bool use_new_name /* = false */) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height, force_fast_update); + return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height, force_fast_update, use_new_name); } // Copy sub image from frame buffer @@ -1356,7 +1361,7 @@ BOOL LLImageGL::createGLTexture() return TRUE ; } -BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category) +BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category, bool defer_copy) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; checkActiveThread(); @@ -1386,6 +1391,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S // Actual image width/height = raw image width/height * 2^discard_level S32 raw_w = imageraw->getWidth() ; S32 raw_h = imageraw->getHeight() ; + S32 w = raw_w << discard_level; S32 h = raw_h << discard_level; @@ -1468,15 +1474,24 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S setCategory(category); const U8* rawdata = imageraw->getData(); - return createGLTexture(discard_level, rawdata, FALSE, usename); + return createGLTexture(discard_level, rawdata, FALSE, usename, defer_copy); } -BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) +BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename, bool defer_copy) + // Call with void data, vmem is allocated but unitialized { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; checkActiveThread(); - llassert(data_in); + if (defer_copy) + { + data_in = nullptr; + } + else + { + llassert(data_in); + } + stop_glerror(); if (discard_level < 0) @@ -1486,7 +1501,8 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); - if (mTexName != 0 && discard_level == mCurrentDiscardLevel) + if (!defer_copy // <--- hacky way to force creation of mNewTexName from media texture update + && mTexName != 0 && discard_level == mCurrentDiscardLevel) { // This will only be true if the size has not changed return setImage(data_in, data_hasmips); @@ -1534,36 +1550,12 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } //if we're on the image loading thread, be sure to delete old_texname and update mTexName on the main thread - if (! on_main_thread()) + if (!on_main_thread()) { + if (!defer_copy) { - LL_PROFILE_ZONE_NAMED("cglt - sync"); - if (gGLManager.mHasSync) - { - auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); - glClientWaitSync(sync, 0, 0); - glDeleteSync(sync); - } - else - { - glFinish(); - } + syncToMainThread(); } - - ref(); - LL::WorkQueue::postMaybe( - mMainQueue, - [=]() - { - LL_PROFILE_ZONE_NAMED("cglt - delete callback"); - if (old_texname != 0) - { - LLImageGL::deleteTextures(1, &old_texname); - } - mTexName = mNewTexName; - mNewTexName = 0; - unref(); - }); } else { @@ -1587,6 +1579,55 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ return TRUE; } +void LLImageGL::syncToMainThread() +{ + { + LL_PROFILE_ZONE_NAMED("cglt - sync"); + if (gGLManager.mHasSync) + { + // post a sync to the main thread (will execute before tex name swap lambda below) + auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + glFlush(); + LL::WorkQueue::postMaybe( + mMainQueue, + [=]() + { + LL_PROFILE_ZONE_NAMED("cglt - wait sync"); + { + LL_PROFILE_ZONE_NAMED("glWaitSync"); + glWaitSync(sync, 0, GL_TIMEOUT_IGNORED); + } + { + LL_PROFILE_ZONE_NAMED("glDeleteSync"); + glDeleteSync(sync); + } + }); + } + else + { + glFinish(); + } + } + + ref(); + LL::WorkQueue::postMaybe( + mMainQueue, + [=]() + { + LL_PROFILE_ZONE_NAMED("cglt - delete callback"); + if (mNewTexName != 0) + { + if (mTexName != 0) + { + LLImageGL::deleteTextures(1, &mTexName); + } + mTexName = mNewTexName; + mNewTexName = 0; + unref(); + } + }); +} + BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const { llassert_always(sAllowReadBackRaw) ; @@ -1714,7 +1755,15 @@ void LLImageGL::destroyGLTexture() mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. mTexName = 0; mGLTextureCreated = FALSE ; - } + } + + // clean up any in-flight name change + if (0 != mNewTexName) + { + // Memory is transient, not tracked by sGlobalTextuerMemory + LLImageGL::deleteTextures(1, &mNewTexName); + mNewTexName = 0; + } } //force to invalidate the gl texture, most likely a sculpty texture -- cgit v1.2.3 From 0d6aa3c0fe184ae00899304cb3f71315f5c73314 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 17 Feb 2022 22:52:23 +0000 Subject: SL-16815 Remove frame stalls from occlusion queries, bumpmap updates, and querying for available video memory. --- indra/llrender/llimagegl.cpp | 119 +++++++++++++++++++++++++++++++------------ 1 file changed, 87 insertions(+), 32 deletions(-) (limited to 'indra/llrender/llimagegl.cpp') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 694c4a7b06..110074bdc0 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -40,6 +40,7 @@ #include "llglslshader.h" #include "llrender.h" #include "llwindow.h" +#include "llframetimer.h" #if !LL_IMAGEGL_THREAD_CHECK #define checkActiveThread() @@ -1075,14 +1076,15 @@ void LLImageGL::postAddToAtlas() stop_glerror(); } -BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update /* = FALSE */, bool use_new_name /* = false */) +BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update /* = FALSE */, LLGLuint use_name) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if (!width || !height) { return TRUE; } - if (0 == (use_new_name ? mNewTexName : mTexName)) + LLGLuint tex_name = use_name != 0 ? use_name : mTexName; + if (0 == tex_name) { // *TODO: Re-enable warning? Ran into thread locking issues? DK 2011-02-18 //LL_WARNS() << "Setting subimage on image without GL texture" << LL_ENDL; @@ -1098,7 +1100,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 // HACK: allow the caller to explicitly force the fast path (i.e. using glTexSubImage2D here instead of calling setImage) even when updating the full texture. if (!force_fast_update && x_pos == 0 && y_pos == 0 && width == getWidth() && height == getHeight() && data_width == width && data_height == height) { - setImage(datap, FALSE, use_new_name ? mNewTexName : mTexName); + setImage(datap, FALSE, tex_name); } else { @@ -1150,7 +1152,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 datap += (y_pos * data_width + x_pos) * getComponents(); // Update the GL texture - BOOL res = gGL.getTexUnit(0)->bindManual(mBindTarget, use_new_name ? mNewTexName : mTexName); + BOOL res = gGL.getTexUnit(0)->bindManual(mBindTarget, tex_name); if (!res) LL_ERRS() << "LLImageGL::setSubImage(): bindTexture failed" << LL_ENDL; stop_glerror(); @@ -1171,10 +1173,10 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 return TRUE; } -BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update /* = FALSE */, bool use_new_name /* = false */) +BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update /* = FALSE */, LLGLuint use_name) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height, force_fast_update, use_new_name); + return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height, force_fast_update, use_name); } // Copy sub image from frame buffer @@ -1361,7 +1363,7 @@ BOOL LLImageGL::createGLTexture() return TRUE ; } -BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category, bool defer_copy) +BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category, bool defer_copy, LLGLuint* tex_name) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; checkActiveThread(); @@ -1474,15 +1476,17 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S setCategory(category); const U8* rawdata = imageraw->getData(); - return createGLTexture(discard_level, rawdata, FALSE, usename, defer_copy); + return createGLTexture(discard_level, rawdata, FALSE, usename, defer_copy, tex_name); } -BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename, bool defer_copy) +BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename, bool defer_copy, LLGLuint* tex_name) // Call with void data, vmem is allocated but unitialized { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; checkActiveThread(); + bool main_thread = on_main_thread(); + if (defer_copy) { data_in = nullptr; @@ -1501,29 +1505,40 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); - if (!defer_copy // <--- hacky way to force creation of mNewTexName from media texture update + if (main_thread // <--- always force creation of mNewTexName when not on main thread && mTexName != 0 && discard_level == mCurrentDiscardLevel) { + LL_PROFILE_ZONE_NAMED("cglt - early setImage"); // This will only be true if the size has not changed + if (tex_name != nullptr) + { + *tex_name = mTexName; + } return setImage(data_in, data_hasmips); } GLuint old_texname = mTexName; - + GLuint new_texname = 0; if (usename != 0) { - mNewTexName = usename; + llassert(main_thread); + new_texname = usename; } else { - LLImageGL::generateTextures(1, &mNewTexName); + LLImageGL::generateTextures(1, &new_texname); { - gGL.getTexUnit(0)->bind(this, false, false, mNewTexName); + gGL.getTexUnit(0)->bind(this, false, false, new_texname); glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel - discard_level); } } + if (tex_name != nullptr) + { + *tex_name = new_texname; + } + if (mUseMipMaps) { mAutoGenMips = gGLManager.mHasMipMapGeneration; @@ -1531,9 +1546,12 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ mCurrentDiscardLevel = discard_level; - if (!setImage(data_in, data_hasmips, mNewTexName)) { - return FALSE; + LL_PROFILE_ZONE_NAMED("cglt - late setImage"); + if (!setImage(data_in, data_hasmips, new_texname)) + { + return FALSE; + } } // Set texture options to our defaults. @@ -1550,11 +1568,11 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } //if we're on the image loading thread, be sure to delete old_texname and update mTexName on the main thread - if (!on_main_thread()) + if (!main_thread) { if (!defer_copy) { - syncToMainThread(); + syncToMainThread(new_texname); } } else @@ -1564,8 +1582,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ { LLImageGL::deleteTextures(1, &old_texname); } - mTexName = mNewTexName; - mNewTexName = 0; + mTexName = new_texname; } mTextureMemory = (S32Bytes)getMipBytes(mCurrentDiscardLevel); @@ -1579,13 +1596,36 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ return TRUE; } -void LLImageGL::syncToMainThread() +void update_free_vram() +{ + LL_PROFILE_ZONE_SCOPED; + + if (gGLManager.mHasATIMemInfo) + { + S32 meminfo[4]; + glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo); + LLImageGLThread::sFreeVRAMMegabytes = meminfo[0]; + + } + else if (gGLManager.mHasNVXMemInfo) + { + S32 free_memory; + glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory); + LLImageGLThread::sFreeVRAMMegabytes = free_memory / 1024; + } +} + +void LLImageGL::syncToMainThread(LLGLuint new_tex_name) { + LL_PROFILE_ZONE_SCOPED; { LL_PROFILE_ZONE_NAMED("cglt - sync"); if (gGLManager.mHasSync) { // post a sync to the main thread (will execute before tex name swap lambda below) + // glFlush calls here are partly superstitious and partly backed by observation + // on AMD hardware + glFlush(); auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); glFlush(); LL::WorkQueue::postMaybe( @@ -1615,17 +1655,27 @@ void LLImageGL::syncToMainThread() [=]() { LL_PROFILE_ZONE_NAMED("cglt - delete callback"); - if (mNewTexName != 0) + if (new_tex_name != 0) { if (mTexName != 0) { LLImageGL::deleteTextures(1, &mTexName); } - mTexName = mNewTexName; - mNewTexName = 0; + mTexName = new_tex_name; unref(); } }); + + + //update free vram periodically + static LLFrameTimer timer; + + if (timer.getElapsedTimeF32() > 1.f) //call this once per second. + { + update_free_vram(); + timer.reset(); + } + } BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const @@ -1756,14 +1806,6 @@ void LLImageGL::destroyGLTexture() mTexName = 0; mGLTextureCreated = FALSE ; } - - // clean up any in-flight name change - if (0 != mNewTexName) - { - // Memory is transient, not tracked by sGlobalTextuerMemory - LLImageGL::deleteTextures(1, &mNewTexName); - mNewTexName = 0; - } } //force to invalidate the gl texture, most likely a sculpty texture @@ -2306,6 +2348,8 @@ void LLImageGL::checkActiveThread() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, nummips); */ +std::atomic LLImageGLThread::sFreeVRAMMegabytes; + LLImageGLThread::LLImageGLThread(LLWindow* window) // We want exactly one thread, but a very large capacity: we never want // anyone, especially inner-loop render code, to have to block on post() @@ -2332,3 +2376,14 @@ void LLImageGLThread::run() gGL.shutdown(); mWindow->destroySharedContext(mContext); } + +S32 LLImageGLThread::getFreeVRAMMegabytes() +{ + if (!sEnabled) + { + update_free_vram(); + } + + return sFreeVRAMMegabytes; +} + -- cgit v1.2.3 From 1c5c45f27317d6ee7c2c30de11f43aeee3855434 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 22 Feb 2022 14:58:50 -0600 Subject: SL-16815 Fix for broken media texture updates when multithreaded GL is disabled. --- indra/llrender/llimagegl.cpp | 86 ++++++++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 38 deletions(-) (limited to 'indra/llrender/llimagegl.cpp') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 110074bdc0..10fdd7c9a9 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1480,7 +1480,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S } BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename, bool defer_copy, LLGLuint* tex_name) - // Call with void data, vmem is allocated but unitialized +// Call with void data, vmem is allocated but unitialized { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; checkActiveThread(); @@ -1505,7 +1505,8 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); - if (main_thread // <--- always force creation of mNewTexName when not on main thread + if (main_thread // <--- always force creation of new_texname when not on main thread ... + && !defer_copy // <--- ... or defer copy is set && mTexName != 0 && discard_level == mCurrentDiscardLevel) { LL_PROFILE_ZONE_NAMED("cglt - early setImage"); @@ -1533,7 +1534,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel - discard_level); } } - + if (tex_name != nullptr) { *tex_name = new_texname; @@ -1568,22 +1569,23 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } //if we're on the image loading thread, be sure to delete old_texname and update mTexName on the main thread - if (!main_thread) + if (!defer_copy) { - if (!defer_copy) + if (!main_thread) { syncToMainThread(new_texname); } - } - else - { - //not on background thread, immediately set mTexName - if (old_texname != 0) + else { - LLImageGL::deleteTextures(1, &old_texname); + //not on background thread, immediately set mTexName + if (old_texname != 0 && old_texname != new_texname) + { + LLImageGL::deleteTextures(1, &old_texname); + } + mTexName = new_texname; } - mTexName = new_texname; } + mTextureMemory = (S32Bytes)getMipBytes(mCurrentDiscardLevel); sGlobalTextureMemory += mTextureMemory; @@ -1596,22 +1598,46 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ return TRUE; } -void update_free_vram() +void LLImageGLThread::updateClass() { LL_PROFILE_ZONE_SCOPED; - if (gGLManager.mHasATIMemInfo) + // update available vram one per second + static LLFrameTimer sTimer; + + if (sTimer.getElapsedSeconds() < 1.f) { - S32 meminfo[4]; - glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo); - LLImageGLThread::sFreeVRAMMegabytes = meminfo[0]; + return; + } + + sTimer.reset(); + + auto func = []() + { + if (gGLManager.mHasATIMemInfo) + { + S32 meminfo[4]; + glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo); + LLImageGLThread::sFreeVRAMMegabytes = meminfo[0]; + } + else if (gGLManager.mHasNVXMemInfo) + { + S32 free_memory; + glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory); + LLImageGLThread::sFreeVRAMMegabytes = free_memory / 1024; + } + }; + + // post update to background thread if available, otherwise execute immediately + auto queue = LLImageGLThread::sEnabled ? LL::WorkQueue::getInstance("LLImageGL") : nullptr; + if (queue) + { + queue->post(func); } - else if (gGLManager.mHasNVXMemInfo) + else { - S32 free_memory; - glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory); - LLImageGLThread::sFreeVRAMMegabytes = free_memory / 1024; + func(); } } @@ -1657,7 +1683,7 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name) LL_PROFILE_ZONE_NAMED("cglt - delete callback"); if (new_tex_name != 0) { - if (mTexName != 0) + if (mTexName != 0 && mTexName != new_tex_name) { LLImageGL::deleteTextures(1, &mTexName); } @@ -1665,17 +1691,6 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name) unref(); } }); - - - //update free vram periodically - static LLFrameTimer timer; - - if (timer.getElapsedTimeF32() > 1.f) //call this once per second. - { - update_free_vram(); - timer.reset(); - } - } BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const @@ -2379,11 +2394,6 @@ void LLImageGLThread::run() S32 LLImageGLThread::getFreeVRAMMegabytes() { - if (!sEnabled) - { - update_free_vram(); - } - return sFreeVRAMMegabytes; } -- cgit v1.2.3 From 74641a121316a13e106d525fb1684c517791766d Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 22 Feb 2022 19:48:01 -0600 Subject: SL-16815 Cleanup -- disable multithreaded bumpmap generation while tracking down loading issues, fix sync issue in single threaded mode in media textures, restore LL_IMAGEGL_THREAD_CHECK functionality --- indra/llrender/llimagegl.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/llrender/llimagegl.cpp') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 10fdd7c9a9..9e26247e1e 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1644,6 +1644,8 @@ void LLImageGLThread::updateClass() void LLImageGL::syncToMainThread(LLGLuint new_tex_name) { LL_PROFILE_ZONE_SCOPED; + llassert(!on_main_thread()); + { LL_PROFILE_ZONE_NAMED("cglt - sync"); if (gGLManager.mHasSync) -- cgit v1.2.3 From d9a68339d5aa18af349e347d6ed74bc01824cec7 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 23 Feb 2022 16:51:33 -0600 Subject: SL-16815 and SL-16906 Avoid redundant bumpmap generation, add some assertions around ref counting and (hack) fix crash on shutdown from dangling texture reference (reduced to 1 dangling texture from several hundred, can't find the remaining reference). --- indra/llrender/llimagegl.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'indra/llrender/llimagegl.cpp') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 9e26247e1e..5cf3a2a15f 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -437,7 +437,7 @@ LLImageGL::LLImageGL( LLImageGL::~LLImageGL() { - if (!mExternalTexture) + if (!mExternalTexture && gGLManager.mInited) { LLImageGL::cleanup(); sImageList.erase(this); @@ -1629,14 +1629,16 @@ void LLImageGLThread::updateClass() } }; + // post update to background thread if available, otherwise execute immediately - auto queue = LLImageGLThread::sEnabled ? LL::WorkQueue::getInstance("LLImageGL") : nullptr; - if (queue) + auto queue = LL::WorkQueue::getInstance("LLImageGL"); + if (sEnabled) { queue->post(func); } else { + llassert(queue == nullptr); func(); } } -- cgit v1.2.3 From fc0b238654091c6090d5d85ceda51fbc6cb71eaa Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 23 Feb 2022 17:55:44 -0600 Subject: Fix for media textures failing to update (and eating lots of memory) on Mac/Intel --- indra/llrender/llimagegl.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'indra/llrender/llimagegl.cpp') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 5cf3a2a15f..63f9a67e2c 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1685,18 +1685,23 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name) [=]() { LL_PROFILE_ZONE_NAMED("cglt - delete callback"); - if (new_tex_name != 0) - { - if (mTexName != 0 && mTexName != new_tex_name) - { - LLImageGL::deleteTextures(1, &mTexName); - } - mTexName = new_tex_name; - unref(); - } + syncTexName(new_tex_name); + unref(); }); } +void LLImageGL::syncTexName(LLGLuint texname) +{ + if (texname != 0) + { + if (mTexName != 0 && mTexName != texname) + { + LLImageGL::deleteTextures(1, &mTexName); + } + mTexName = texname; + } +} + BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const { llassert_always(sAllowReadBackRaw) ; -- cgit v1.2.3 From 4f9fa5e817c44d2ba0bc5558955085f48b280861 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 23 Feb 2022 19:53:49 -0600 Subject: Fix for some GPUs thinking they have 0 available vram. --- indra/llrender/llimagegl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llrender/llimagegl.cpp') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 63f9a67e2c..230d2b3dd0 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -2372,7 +2372,7 @@ void LLImageGL::checkActiveThread() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, nummips); */ -std::atomic LLImageGLThread::sFreeVRAMMegabytes; +std::atomic LLImageGLThread::sFreeVRAMMegabytes = 4096; //if free vram is unknown, default to 4GB LLImageGLThread::LLImageGLThread(LLWindow* window) // We want exactly one thread, but a very large capacity: we never want -- cgit v1.2.3 From 85e480616de4e741f9f34a396677002d86a1d660 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 23 Feb 2022 19:59:46 -0600 Subject: Fix for mac build --- indra/llrender/llimagegl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llrender/llimagegl.cpp') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 230d2b3dd0..f43671dee5 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -2372,7 +2372,7 @@ void LLImageGL::checkActiveThread() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, nummips); */ -std::atomic LLImageGLThread::sFreeVRAMMegabytes = 4096; //if free vram is unknown, default to 4GB +std::atomic LLImageGLThread::sFreeVRAMMegabytes(4096); //if free vram is unknown, default to 4GB LLImageGLThread::LLImageGLThread(LLWindow* window) // We want exactly one thread, but a very large capacity: we never want -- cgit v1.2.3