summaryrefslogtreecommitdiff
path: root/indra/llrender/llimagegl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llrender/llimagegl.cpp')
-rw-r--r--indra/llrender/llimagegl.cpp64
1 files changed, 48 insertions, 16 deletions
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index a40cb14f17..eb86f5bae2 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -166,6 +166,8 @@ U64 LLImageGL::getTextureBytesAllocated()
//statics
U32 LLImageGL::sUniqueCount = 0;
+std::atomic<U32> LLImageGL::sOOMErrorCount(0);
+thread_local bool LLImageGL::sStampBindFrame = true;
U32 LLImageGL::sBindCount = 0;
S32 LLImageGL::sCount = 0;
@@ -526,7 +528,7 @@ bool LLImageGL::create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, b
//----------------------------------------------------------------------------
LLImageGL::LLImageGL(bool usemipmaps/* = true*/, bool allow_compression/* = true*/)
-: mSaveData(0), mExternalTexture(false)
+: mExternalTexture(false)
{
init(usemipmaps, allow_compression);
setSize(0, 0, 0);
@@ -535,7 +537,7 @@ LLImageGL::LLImageGL(bool usemipmaps/* = true*/, bool allow_compression/* = true
}
LLImageGL::LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps/* = true*/, bool allow_compression/* = true*/)
-: mSaveData(0), mExternalTexture(false)
+: mExternalTexture(false)
{
llassert( components <= 4 );
init(usemipmaps, allow_compression);
@@ -545,7 +547,7 @@ LLImageGL::LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps/* = t
}
LLImageGL::LLImageGL(const LLImageRaw* imageraw, bool usemipmaps/* = true*/, bool allow_compression/* = true*/)
-: mSaveData(0), mExternalTexture(false)
+: mExternalTexture(false)
{
init(usemipmaps, allow_compression);
setSize(0, 0, 0);
@@ -654,8 +656,6 @@ void LLImageGL::cleanup()
destroyGLTexture();
}
freePickMask();
-
- mSaveData = NULL; // deletes data
}
//----------------------------------------------------------------------------
@@ -812,6 +812,7 @@ void LLImageGL::setImage(const LLImageRaw* imageraw)
bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 usename /* = 0 */)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+ LLImageGLStampBypass no_stamp; // upload binds are not visibility
const bool is_compressed = isCompressed();
@@ -1591,6 +1592,12 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
{
free_cur_tex_image();
}
+
+ // Drain stale GL errors so an OOM detected below belongs to this alloc.
+ // Otherwise a failed glTexImage2D is swallowed in release while
+ // alloc_tex_image still counts the bytes, inflating the used-VRAM figure.
+ while (glGetError() != GL_NO_ERROR) {}
+
const bool use_sub_image = should_stagger_image_set(compress);
if (!use_sub_image)
{
@@ -1600,19 +1607,30 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
else
{
// break up calls to a manageable size for the GL command buffer
- {
- LL_PROFILE_ZONE_NAMED("glTexImage2D alloc");
- glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, nullptr);
- }
+ LL_PROFILE_ZONE_NAMED("glTexImage2D alloc");
+ glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, nullptr);
+ }
- U8* src = (U8*)(pixels);
- if (src)
+ if (glGetError() == GL_OUT_OF_MEMORY)
+ {
+ ++sOOMErrorCount;
+ LL_WARNS_ONCE("Texture") << "glTexImage2D failed with GL_OUT_OF_MEMORY ("
+ << width << "x" << height << " mip " << miplevel
+ << ") - not counting bytes" << LL_ENDL;
+ }
+ else
+ {
+ if (use_sub_image)
{
- LL_PROFILE_ZONE_NAMED("glTexImage2D copy");
- sub_image_lines(target, miplevel, 0, 0, width, height, pixformat, pixtype, src, width);
+ U8* src = (U8*)(pixels);
+ if (src)
+ {
+ LL_PROFILE_ZONE_NAMED("glTexImage2D copy");
+ sub_image_lines(target, miplevel, 0, 0, width, height, pixformat, pixtype, src, width);
+ }
}
+ alloc_tex_image(width, height, intformat, 1);
}
- alloc_tex_image(width, height, intformat, 1);
}
stop_glerror();
}
@@ -1765,6 +1783,7 @@ bool LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, bool data_
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LL_PROFILE_GPU_ZONE("createGLTexture");
checkActiveThread();
+ LLImageGLStampBypass no_stamp; // creation binds are not visibility
bool main_thread = on_main_thread();
@@ -2191,12 +2210,21 @@ S32 LLImageGL::dimDerivedMaxDiscard(S32 width, S32 height)
void LLImageGL::stampBound() const
{
- // Skip the store on same-frame re-binds - bindFast is per-draw and
- // would dirty this cache line per bind per texture otherwise.
+ // Both stamps skip same-frame re-binds (bindFast runs per draw). They dedupe
+ // separately, so a non-camera pass touching the time stamp first doesn't stop
+ // a real camera bind from setting the frame stamp later the same frame.
if (mLastBindTime != sLastFrameTime)
{
mLastBindTime = sLastFrameTime;
}
+ if (sStampBindFrame)
+ {
+ const U32 frame = LLFrameTimer::getFrameCount();
+ if (mLastBindFrame != frame)
+ {
+ mLastBindFrame = frame;
+ }
+ }
}
S64 LLImageGL::getBytes(S32 discard_level) const
@@ -2637,6 +2665,10 @@ bool LLImageGL::scaleDown(S32 desired_discard)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+ // Don't let eviction re-arm visibility: the glGenerateMipmap re-bind below
+ // would otherwise stamp mLastBindFrame and keep the texture fetch-eligible.
+ LLImageGLStampBypass no_stamp;
+
if (mTarget != GL_TEXTURE_2D
|| mFormatInternal == -1 // not initialized
)