summaryrefslogtreecommitdiff
path: root/indra/llrender
diff options
context:
space:
mode:
authorDave Parks <davep@lindenlab.com>2024-07-03 17:42:24 -0500
committerGitHub <noreply@github.com>2024-07-03 17:42:24 -0500
commit08b933a0c67463f06f124420f16c8a3f7dc83f1f (patch)
tree4ca6d47a6b055d332cb75646226c13e950f37ce4 /indra/llrender
parent9a38ecee8ef54b3e85a88657d7ba96c3292e350e (diff)
#1870 Tune up for better experience on integrated intel with low memory (#1872)
* More deterministic vsize calculation. Add control for choosing downscale method. * Quick hack to make GLTF preview work again
Diffstat (limited to 'indra/llrender')
-rw-r--r--indra/llrender/llgl.h3
-rw-r--r--indra/llrender/llimagegl.cpp126
-rw-r--r--indra/llrender/llimagegl.h5
-rw-r--r--indra/llrender/llrender.h6
-rw-r--r--indra/llrender/llrendertarget.cpp12
-rw-r--r--indra/llrender/llrendertarget.h4
6 files changed, 120 insertions, 36 deletions
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 909dad2e85..be1c0a532a 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -102,6 +102,9 @@ public:
bool mIsNVIDIA;
bool mIsIntel;
+ // hints to the render pipe
+ U32 mDownScaleMethod = 0; // see settings.xml RenderDownScaleMethod
+
#if LL_DARWIN
// Needed to distinguish problem cards on older Macs that break with Materials
bool mIsMobileGF;
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 956bcef352..34200ef5cb 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -57,6 +57,9 @@ const F32 MIN_TEXTURE_LIFETIME = 10.f;
U32 wpo2(U32 i);
+U32 LLImageGL::sFrameCount = 0;
+
+
// texture memory accounting (for macOS)
static LLMutex sTexMemMutex;
static std::unordered_map<U32, U64> sTextureAllocs;
@@ -1003,7 +1006,7 @@ bool should_stagger_image_set(bool compressed)
#else
// glTexSubImage2D doesn't work with compressed textures on select tested Nvidia GPUs on Windows 10 -Cosmic,2023-03-08
// Setting media textures off-thread seems faster when not using sub_image_lines (Nvidia/Windows 10) -Cosmic,2023-03-31
- return !compressed && on_main_thread();
+ return !compressed && on_main_thread() && !gGLManager.mIsIntel;
#endif
}
@@ -1186,12 +1189,36 @@ void LLImageGL::generateTextures(S32 numTextures, U32 *textures)
}
// static
+void LLImageGL::updateClass()
+{
+ sFrameCount++;
+}
+
+// static
void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures)
{
+ // wait a few frames before actually deleting the textures to avoid
+ // synchronization issues with the GPU
+ static std::vector<U32> sFreeList[4];
+
if (gGLManager.mInited)
{
- free_tex_images(numTextures, textures);
- glDeleteTextures(numTextures, textures);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+ U32 idx = sFrameCount % 4;
+
+ for (S32 i = 0; i < numTextures; ++i)
+ {
+ sFreeList[idx].push_back(textures[i]);
+ }
+
+ idx = (sFrameCount + 3) % 4;
+
+ if (!sFreeList[idx].empty())
+ {
+ glDeleteTextures((GLsizei) sFreeList[idx].size(), sFreeList[idx].data());
+ free_tex_images((GLsizei) sFreeList[idx].size(), sFreeList[idx].data());
+ sFreeList[idx].resize(0);
+ }
}
}
@@ -2335,44 +2362,85 @@ bool LLImageGL::scaleDown(S32 desired_discard)
S32 desired_width = getWidth(desired_discard);
S32 desired_height = getHeight(desired_discard);
- U64 size = getBytes(desired_discard);
- llassert(size <= 2048*2048*4); // we shouldn't be using this method to downscale huge textures, but it'll work
- gGL.getTexUnit(0)->bind(this);
+ if (gGLManager.mDownScaleMethod == 0)
+ { // use an FBO to downscale the texture
+ // allocate new texture
+ U32 temp_texname = 0;
+ generateTextures(1, &temp_texname);
+ 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);
+ }
+ // account for new texture getting created
+ alloc_tex_image(desired_width, desired_height, mFormatPrimary);
- if (sScratchPBO == 0)
- {
- glGenBuffers(1, &sScratchPBO);
- sScratchPBOSize = 0;
- }
+ // Use render-to-texture to scale down the texture
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glFramebufferTexture2D");
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTarget, temp_texname, 0);
+ }
- glBindBuffer(GL_PIXEL_PACK_BUFFER, sScratchPBO);
+ glViewport(0, 0, desired_width, desired_height);
- if (size > sScratchPBOSize)
- {
- glBufferData(GL_PIXEL_PACK_BUFFER, size, NULL, GL_STREAM_COPY);
- sScratchPBOSize = size;
+ // draw a full screen triangle
+ gGL.getTexUnit(0)->bind(this);
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ // delete old texture and assign new texture name
+ deleteTextures(1, &mTexName);
+ mTexName = temp_texname;
+
+ if (mHasMipMaps)
+ { // generate mipmaps if needed
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glGenerateMipmap");
+ gGL.getTexUnit(0)->bind(this);
+ glGenerateMipmap(mTarget);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ }
}
+ else
+ { // use a PBO to downscale the texture
+ U64 size = getBytes(desired_discard);
+ llassert(size <= 2048 * 2048 * 4); // we shouldn't be using this method to downscale huge textures, but it'll work
+ gGL.getTexUnit(0)->bind(this);
+
+ if (sScratchPBO == 0)
+ {
+ glGenBuffers(1, &sScratchPBO);
+ sScratchPBOSize = 0;
+ }
- glGetTexImage(mTarget, mip, mFormatPrimary, mFormatType, nullptr);
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, sScratchPBO);
- free_tex_image(mTexName);
+ if (size > sScratchPBOSize)
+ {
+ glBufferData(GL_PIXEL_PACK_BUFFER, size, NULL, GL_STREAM_COPY);
+ sScratchPBOSize = size;
+ }
- glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+ glGetTexImage(mTarget, mip, mFormatPrimary, mFormatType, nullptr);
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, sScratchPBO);
- glTexImage2D(mTarget, 0, mFormatPrimary, desired_width, desired_height, 0, mFormatPrimary, mFormatType, nullptr);
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+ free_tex_image(mTexName);
- alloc_tex_image(desired_width, desired_height, mFormatPrimary);
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
- if (mHasMipMaps)
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glGenerateMipmap");
- glGenerateMipmap(mTarget);
- }
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, sScratchPBO);
+ glTexImage2D(mTarget, 0, mFormatPrimary, desired_width, desired_height, 0, mFormatPrimary, mFormatType, nullptr);
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ alloc_tex_image(desired_width, desired_height, mFormatPrimary);
+
+ if (mHasMipMaps)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glGenerateMipmap");
+ glGenerateMipmap(mTarget);
+ }
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ }
mCurrentDiscardLevel = desired_discard;
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 3892e9c014..5073701c30 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -62,6 +62,9 @@ class LLImageGL : public LLRefCount
friend class LLTexUnit;
public:
+ // call once per frame
+ static void updateClass();
+
// Get an estimate of how many bytes have been allocated in vram for textures.
// Does not include mipmaps.
// NOTE: multiplying this number by two gives a good estimate for total
@@ -276,7 +279,7 @@ protected:
public:
static std::unordered_set<LLImageGL*> sImageList;
static S32 sCount;
-
+ static U32 sFrameCount;
static F32 sLastFrameTime;
// Global memory statistics
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index be9f3895e7..e6b4118beb 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -297,7 +297,11 @@ public:
ALTERNATE_DIFFUSE_MAP = 1,
NORMAL_MAP = 1,
SPECULAR_MAP = 2,
- NUM_TEXTURE_CHANNELS = 3,
+ BASECOLOR_MAP = 3,
+ METALLIC_ROUGHNESS_MAP = 4,
+ GLTF_NORMAL_MAP = 5,
+ EMISSIVE_MAP = 6,
+ NUM_TEXTURE_CHANNELS = 7,
};
enum eVolumeTexIndex : U8
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index efdde77a32..60159a0497 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -426,14 +426,17 @@ void LLRenderTarget::bindTarget()
GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2,
GL_COLOR_ATTACHMENT3};
- glDrawBuffers(static_cast<GLsizei>(mTex.size()), drawbuffers);
if (mTex.empty())
{ //no color buffer to draw to
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
}
-
+ else
+ {
+ glDrawBuffers(static_cast<GLsizei>(mTex.size()), drawbuffers);
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+ }
check_framebuffer_status();
glViewport(0, 0, mResX, mResY);
@@ -519,7 +522,8 @@ void LLRenderTarget::flush()
llassert(sCurFBO == mFBO);
llassert(sBoundTarget == this);
- if (mGenerateMipMaps == LLTexUnit::TMG_AUTO) {
+ if (mGenerateMipMaps == LLTexUnit::TMG_AUTO)
+ {
LL_PROFILE_GPU_ZONE("rt generate mipmaps");
bindTexture(0, 0, LLTexUnit::TFO_TRILINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
@@ -540,6 +544,8 @@ void LLRenderTarget::flush()
glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
sCurResX = gGLViewport[2];
sCurResY = gGLViewport[3];
+ glReadBuffer(GL_BACK);
+ glDrawBuffer(GL_BACK);
}
}
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index 340276a752..a1adf93fa1 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -172,6 +172,8 @@ public:
// *HACK
void swapFBORefs(LLRenderTarget& other);
+ static LLRenderTarget* sBoundTarget;
+
protected:
U32 mResX;
U32 mResY;
@@ -186,8 +188,6 @@ protected:
U32 mMipLevels;
LLTexUnit::eTextureType mUsage;
-
- static LLRenderTarget* sBoundTarget;
};
#endif