* More deterministic vsize calculation. Add control for choosing downscale method. * Quick hack to make GLTF preview work againmaster
parent
9a38ecee8e
commit
08b933a0c6
|
|
@ -79,6 +79,7 @@ LLFileSystem::~LLFileSystem()
|
|||
// static
|
||||
bool LLFileSystem::getExists(const LLUUID& file_id, const LLAssetType::EType file_type)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
std::string id_str;
|
||||
file_id.toString(id_str);
|
||||
const std::string extra_info = "";
|
||||
|
|
|
|||
|
|
@ -484,6 +484,8 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
|
|||
void *user_data,
|
||||
bool is_priority)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
LL_DEBUGS("AssetStorage") << "LLAssetStorage::getAssetData() - " << uuid << "," << LLAssetType::lookup(type) << LL_ENDL;
|
||||
|
||||
LL_DEBUGS("AssetStorage") << "ASSET_TRACE requesting " << uuid << " type " << LLAssetType::lookup(type) << LL_ENDL;
|
||||
|
|
@ -529,6 +531,7 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
|
|||
|
||||
if (size > 0)
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED("gad - file in cache");
|
||||
// we've already got the file
|
||||
// theoretically, partial files w/o a pending request shouldn't happen
|
||||
// unless there's a weird error
|
||||
|
|
@ -548,7 +551,7 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
|
|||
}
|
||||
|
||||
bool duplicate = false;
|
||||
|
||||
LL_PROFILE_ZONE_NAMED("gad - check pending downloads");
|
||||
// check to see if there's a pending download of this uuid already
|
||||
for (request_list_t::iterator iter = mPendingDownloads.begin();
|
||||
iter != mPendingDownloads.end(); ++iter )
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
@ -1185,13 +1188,37 @@ 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,45 +2362,86 @@ 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);
|
||||
}
|
||||
|
||||
glViewport(0, 0, desired_width, desired_height);
|
||||
|
||||
// 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);
|
||||
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, sScratchPBO);
|
||||
if (sScratchPBO == 0)
|
||||
{
|
||||
glGenBuffers(1, &sScratchPBO);
|
||||
sScratchPBOSize = 0;
|
||||
}
|
||||
|
||||
if (size > sScratchPBOSize)
|
||||
{
|
||||
glBufferData(GL_PIXEL_PACK_BUFFER, size, NULL, GL_STREAM_COPY);
|
||||
sScratchPBOSize = size;
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, sScratchPBO);
|
||||
|
||||
if (size > sScratchPBOSize)
|
||||
{
|
||||
glBufferData(GL_PIXEL_PACK_BUFFER, size, NULL, GL_STREAM_COPY);
|
||||
sScratchPBOSize = size;
|
||||
}
|
||||
|
||||
glGetTexImage(mTarget, mip, mFormatPrimary, mFormatType, nullptr);
|
||||
|
||||
free_tex_image(mTexName);
|
||||
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, sScratchPBO);
|
||||
glTexImage2D(mTarget, 0, mFormatPrimary, desired_width, desired_height, 0, mFormatPrimary, mFormatType, nullptr);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
glGetTexImage(mTarget, mip, mFormatPrimary, mFormatType, nullptr);
|
||||
|
||||
free_tex_image(mTexName);
|
||||
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, sScratchPBO);
|
||||
glTexImage2D(mTarget, 0, mFormatPrimary, desired_width, desired_height, 0, mFormatPrimary, mFormatType, nullptr);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
|
||||
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;
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -7732,7 +7732,7 @@
|
|||
<key>Comment</key>
|
||||
<string>Minimum of available physical memory in MB before textures get scaled down</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
|
|
@ -7771,6 +7771,17 @@
|
|||
<key>Value</key>
|
||||
<integer>2048</integer>
|
||||
</map>
|
||||
<key>RenderDownScaleMethod</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Method to use to downscale images. 0 - FBO, 1 - PBO</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>RenderDebugTextureBind</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
version 60
|
||||
version 61
|
||||
// The version number above should be incremented IF AND ONLY IF some
|
||||
// change has been made that is sufficiently important to justify
|
||||
// resetting the graphics preferences of all users to the recommended
|
||||
|
|
@ -76,6 +76,7 @@ RenderGLMultiThreadedMedia 1 1
|
|||
RenderReflectionProbeResolution 1 128
|
||||
RenderScreenSpaceReflections 1 1
|
||||
RenderMirrors 1 1
|
||||
RenderDownScaleMethod 1 1
|
||||
|
||||
|
||||
//
|
||||
|
|
@ -366,6 +367,7 @@ RenderAnisotropic 1 0
|
|||
RenderFSAASamples 1 0
|
||||
RenderGLContextCoreProfile 1 0
|
||||
RenderGLMultiThreadedMedia 1 0
|
||||
RenderDownScaleMethod 1 0
|
||||
|
||||
list AMD
|
||||
RenderGLMultiThreadedTextures 1 1
|
||||
|
|
|
|||
|
|
@ -36,8 +36,6 @@ namespace LL
|
|||
{
|
||||
namespace GLTF
|
||||
{
|
||||
constexpr S32 INVALID_INDEX = -1;
|
||||
|
||||
class Buffer
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -476,6 +476,7 @@ void Asset::update()
|
|||
{ // HACK - force texture to be loaded full rez
|
||||
// TODO: calculate actual vsize
|
||||
image.mTexture->addTextureStats(2048.f * 2048.f);
|
||||
image.mTexture->setBoostLevel(LLViewerTexture::BOOST_HIGH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ namespace LL
|
|||
{
|
||||
namespace GLTF
|
||||
{
|
||||
constexpr S32 INVALID_INDEX = -1;
|
||||
|
||||
using Value = boost::json::value;
|
||||
|
||||
using mat4 = glm::mat4;
|
||||
|
|
|
|||
|
|
@ -345,6 +345,12 @@ void GLTFSceneManager::addGLTFObject(LLViewerObject* obj, LLUUID gltf_id)
|
|||
llassert(obj->getVolume()->getParams().getSculptID() == gltf_id);
|
||||
llassert(obj->getVolume()->getParams().getSculptType() == LL_SCULPT_TYPE_GLTF);
|
||||
|
||||
if (obj->mGLTFAsset)
|
||||
{ // object already has a GLTF asset, don't reload it
|
||||
llassert(std::find(mObjects.begin(), mObjects.end(), obj) != mObjects.end());
|
||||
return;
|
||||
}
|
||||
|
||||
obj->ref();
|
||||
gAssetStorage->getAssetData(gltf_id, LLAssetType::AT_GLTF, onGLTFLoadComplete, obj);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2210,10 +2210,10 @@ bool LLAppViewer::initThreads()
|
|||
cores = llmin(cores, (S32) max_cores);
|
||||
}
|
||||
|
||||
// The only configurable thread count right now is ImageDecode
|
||||
// The viewer typically starts around 8 threads not including image decode,
|
||||
// so try to leave at least one core free
|
||||
S32 image_decode_count = llclamp(cores - 9, 1, 8);
|
||||
// always use at least 2 threads for image decoding to prevent
|
||||
// a single texture blocking all other textures from decoding
|
||||
S32 image_decode_count = llclamp(cores - 6, 2, 16);
|
||||
|
||||
threadCounts["ImageDecode"] = image_decode_count;
|
||||
gSavedSettings.setLLSD("ThreadPoolSizes", threadCounts);
|
||||
|
||||
|
|
@ -4609,6 +4609,10 @@ void LLAppViewer::idle()
|
|||
|
||||
LLGLTFMaterialList::flushUpdates();
|
||||
|
||||
static LLCachedControl<U32> downscale_method(gSavedSettings, "RenderDownScaleMethod");
|
||||
gGLManager.mDownScaleMethod = downscale_method;
|
||||
LLImageGL::updateClass();
|
||||
|
||||
// Service the WorkQueue we use for replies from worker threads.
|
||||
// Use function statics for the timeslice setting so we only have to fetch
|
||||
// and convert MainWorkTime once.
|
||||
|
|
|
|||
|
|
@ -81,10 +81,6 @@ LLDrawPoolAlpha::~LLDrawPoolAlpha()
|
|||
void LLDrawPoolAlpha::prerender()
|
||||
{
|
||||
mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
|
||||
|
||||
// TODO: is this even necessay? These are probably set to never discard
|
||||
LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(1024.f*1024.f);
|
||||
LLViewerFetchedTexture::sWhiteImagep->addTextureStats(1024.f * 1024.f);
|
||||
}
|
||||
|
||||
S32 LLDrawPoolAlpha::getNumPostDeferredPasses()
|
||||
|
|
|
|||
|
|
@ -169,6 +169,8 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
|
|||
mImportanceToCamera = 0.f ;
|
||||
mBoundingSphereRadius = 0.0f ;
|
||||
|
||||
mTexExtents[0].set(0, 0);
|
||||
mTexExtents[1].set(1, 1);
|
||||
mHasMedia = false ;
|
||||
mIsMediaAllowed = true;
|
||||
}
|
||||
|
|
@ -2047,10 +2049,12 @@ void LLFace::resetVirtualSize()
|
|||
F32 LLFace::getTextureVirtualSize()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
|
||||
|
||||
F32 radius;
|
||||
F32 cos_angle_to_view_dir;
|
||||
bool in_frustum = calcPixelArea(cos_angle_to_view_dir, radius);
|
||||
|
||||
|
||||
if (mPixelArea < F_ALMOST_ZERO || !in_frustum)
|
||||
{
|
||||
setVirtualSize(0.f) ;
|
||||
|
|
|
|||
|
|
@ -530,6 +530,9 @@ void LLGLTexMemBar::draw()
|
|||
F64 raw_image_bytes_MB = raw_image_bytes / (1024.0 * 1024.0);
|
||||
F64 saved_raw_image_bytes_MB = saved_raw_image_bytes / (1024.0 * 1024.0);
|
||||
F64 aux_raw_image_bytes_MB = aux_raw_image_bytes / (1024.0 * 1024.0);
|
||||
F64 texture_bytes_alloc = LLImageGL::getTextureBytesAllocated() / 1024.0 / 1024.0 * 1.3333f; // add 33% for mipmaps
|
||||
F64 vertex_bytes_alloc = LLVertexBuffer::getBytesAllocated() / 1024.0 / 1024.0;
|
||||
F64 render_bytes_alloc = LLRenderTarget::sBytesAllocated / 1024.0 / 1024.0;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
LLGLSUIDefault gls_ui;
|
||||
|
|
@ -559,7 +562,7 @@ void LLGLTexMemBar::draw()
|
|||
|
||||
// draw a background above first line.... no idea where the rest of the background comes from for the below text
|
||||
gGL.color4f(0.f, 0.f, 0.f, 0.25f);
|
||||
gl_rect_2d(-10, getRect().getHeight() + line_height + 1, getRect().getWidth()+2, getRect().getHeight()+2);
|
||||
gl_rect_2d(-10, getRect().getHeight() + line_height*2 + 1, getRect().getWidth()+2, getRect().getHeight()+2);
|
||||
|
||||
text = llformat("Est. Free: %d MB Sys Free: %d MB FBO: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
|
||||
(S32)LLViewerTexture::sFreeVRAMMegabytes,
|
||||
|
|
@ -568,12 +571,20 @@ void LLGLTexMemBar::draw()
|
|||
discard_bias,
|
||||
cache_usage,
|
||||
cache_max_usage);
|
||||
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*7,
|
||||
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*8,
|
||||
text_color, LLFontGL::LEFT, LLFontGL::TOP);
|
||||
|
||||
text = llformat("Images: %d Raw: %d (%.2f MB) Saved: %d (%.2f MB) Aux: %d (%.2f MB)", image_count, raw_image_count, raw_image_bytes_MB,
|
||||
saved_raw_image_count, saved_raw_image_bytes_MB,
|
||||
aux_raw_image_count, aux_raw_image_bytes_MB);
|
||||
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height * 7,
|
||||
text_color, LLFontGL::LEFT, LLFontGL::TOP);
|
||||
|
||||
text = llformat("Textures: %.2f MB Vertex: %.2f MB Render: %.2f MB Total: %.2f MB",
|
||||
texture_bytes_alloc,
|
||||
vertex_bytes_alloc,
|
||||
render_bytes_alloc,
|
||||
texture_bytes_alloc+vertex_bytes_alloc+render_bytes_alloc);
|
||||
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height * 6,
|
||||
text_color, LLFontGL::LEFT, LLFontGL::TOP);
|
||||
|
||||
|
|
|
|||
|
|
@ -376,6 +376,7 @@ void LLViewerAssetStorage::queueRequestHttp(
|
|||
bool duplicate,
|
||||
bool is_priority)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
LL_DEBUGS("ViewerAsset") << "Request asset via HTTP " << uuid << " type " << LLAssetType::lookup(atype) << LL_ENDL;
|
||||
|
||||
bool with_http = true;
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ S32 LLViewerTexture::sRawCount = 0;
|
|||
S32 LLViewerTexture::sAuxCount = 0;
|
||||
LLFrameTimer LLViewerTexture::sEvaluationTimer;
|
||||
F32 LLViewerTexture::sDesiredDiscardBias = 0.f;
|
||||
F32 LLViewerTexture::sDesiredDiscardScale = 1.1f;
|
||||
|
||||
S32 LLViewerTexture::sMaxSculptRez = 128; //max sculpt image size
|
||||
const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64;
|
||||
const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez;
|
||||
|
|
@ -513,15 +513,18 @@ void LLViewerTexture::updateClass()
|
|||
F32 target = llmax(budget - 512.f, MIN_VRAM_BUDGET);
|
||||
sFreeVRAMMegabytes = target - used;
|
||||
|
||||
F32 over_pct = llmax((used-target) / target, 0.f);
|
||||
F32 over_pct = (used - target) / target;
|
||||
|
||||
bool is_low = over_pct > 0.f;
|
||||
|
||||
if (isSystemMemoryLow())
|
||||
{
|
||||
is_low = true;
|
||||
// System RAM is low -> ramp up discard bias over time to free memory
|
||||
if (sEvaluationTimer.getElapsedTimeF32() > MEMORY_CHECK_WAIT_TIME)
|
||||
{
|
||||
static LLCachedControl<F32> low_mem_min_discard_increment(gSavedSettings, "RenderLowMemMinDiscardIncrement", .1f);
|
||||
sDesiredDiscardBias += llmax(low_mem_min_discard_increment, over_pct);
|
||||
sDesiredDiscardBias += (F32) low_mem_min_discard_increment * (F32) gFrameIntervalSeconds;
|
||||
sEvaluationTimer.reset();
|
||||
}
|
||||
}
|
||||
|
|
@ -529,12 +532,28 @@ void LLViewerTexture::updateClass()
|
|||
{
|
||||
sDesiredDiscardBias = llmax(sDesiredDiscardBias, 1.f + over_pct);
|
||||
|
||||
if (sDesiredDiscardBias > 1.f)
|
||||
if (sDesiredDiscardBias > 1.f && over_pct < 0.f)
|
||||
{
|
||||
sDesiredDiscardBias -= gFrameIntervalSeconds * 0.01;
|
||||
}
|
||||
}
|
||||
|
||||
static bool was_low = false;
|
||||
if (is_low && !was_low)
|
||||
{
|
||||
LL_WARNS() << "Low system memory detected, emergency downrezzing off screen textures" << LL_ENDL;
|
||||
sDesiredDiscardBias = llmax(sDesiredDiscardBias, 1.5f);
|
||||
|
||||
for (auto image : gTextureList)
|
||||
{
|
||||
gTextureList.updateImageDecodePriority(image);
|
||||
}
|
||||
}
|
||||
|
||||
was_low = is_low;
|
||||
|
||||
sDesiredDiscardBias = llclamp(sDesiredDiscardBias, 1.f, 3.f);
|
||||
|
||||
LLViewerTexture::sFreezeImageUpdates = false;
|
||||
}
|
||||
|
||||
|
|
@ -615,16 +634,15 @@ void LLViewerTexture::init(bool firstinit)
|
|||
mParcelMedia = NULL;
|
||||
|
||||
memset(&mNumVolumes, 0, sizeof(U32)* LLRender::NUM_VOLUME_TEXTURE_CHANNELS);
|
||||
mFaceList[LLRender::DIFFUSE_MAP].clear();
|
||||
mFaceList[LLRender::NORMAL_MAP].clear();
|
||||
mFaceList[LLRender::SPECULAR_MAP].clear();
|
||||
mNumFaces[LLRender::DIFFUSE_MAP] =
|
||||
mNumFaces[LLRender::NORMAL_MAP] =
|
||||
mNumFaces[LLRender::SPECULAR_MAP] = 0;
|
||||
|
||||
mVolumeList[LLRender::LIGHT_TEX].clear();
|
||||
mVolumeList[LLRender::SCULPT_TEX].clear();
|
||||
|
||||
for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; i++)
|
||||
{
|
||||
mNumFaces[i] = 0;
|
||||
mFaceList[i].clear();
|
||||
}
|
||||
|
||||
mMainQueue = LL::WorkQueue::getInstance("mainloop");
|
||||
mImageQueue = LL::WorkQueue::getInstance("LLImageGL");
|
||||
}
|
||||
|
|
@ -1608,7 +1626,11 @@ void LLViewerFetchedTexture::scheduleCreateTexture()
|
|||
}
|
||||
else
|
||||
{
|
||||
gTextureList.mCreateTextureList.insert(this);
|
||||
if (!mCreatePending)
|
||||
{
|
||||
mCreatePending = true;
|
||||
gTextureList.mCreateTextureList.push(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1632,13 +1654,12 @@ void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height)
|
|||
|
||||
void LLViewerFetchedTexture::setDebugText(const std::string& text)
|
||||
{
|
||||
for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch)
|
||||
for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
|
||||
{
|
||||
llassert(mNumFaces[ch] <= mFaceList[ch].size());
|
||||
|
||||
for (U32 i = 0; i < mNumFaces[ch]; i++)
|
||||
for (S32 fi = 0; fi < getNumFaces(i); ++fi)
|
||||
{
|
||||
LLFace* facep = mFaceList[ch][i];
|
||||
LLFace* facep = (*(getFaceList(i)))[fi];
|
||||
|
||||
if (facep)
|
||||
{
|
||||
LLDrawable* drawable = facep->getDrawable();
|
||||
|
|
@ -1651,10 +1672,15 @@ void LLViewerFetchedTexture::setDebugText(const std::string& text)
|
|||
}
|
||||
}
|
||||
|
||||
extern bool gCubeSnapshot;
|
||||
|
||||
//virtual
|
||||
void LLViewerFetchedTexture::processTextureStats()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
|
||||
llassert(!gCubeSnapshot); // should only be called when the main camera is active
|
||||
llassert(!LLPipeline::sShadowRender);
|
||||
|
||||
if(mFullyLoaded)
|
||||
{
|
||||
if(mDesiredDiscardLevel > mMinDesiredDiscardLevel)//need to load more
|
||||
|
|
@ -2859,6 +2885,8 @@ void LLViewerLODTexture::processTextureStats()
|
|||
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
|
||||
updateVirtualSize();
|
||||
|
||||
bool did_downscale = false;
|
||||
|
||||
static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes", false);
|
||||
|
||||
{ // restrict texture resolution to download based on RenderMaxTextureResolution
|
||||
|
|
@ -2916,10 +2944,7 @@ void LLViewerLODTexture::processTextureStats()
|
|||
mDiscardVirtualSize = mMaxVirtualSize;
|
||||
mCalculatedDiscardLevel = discard_level;
|
||||
}
|
||||
if (mBoostLevel < LLGLTexture::BOOST_SCULPTED)
|
||||
{
|
||||
discard_level *= sDesiredDiscardScale; // scale (default 1.1f)
|
||||
}
|
||||
|
||||
discard_level = floorf(discard_level);
|
||||
|
||||
F32 min_discard = 0.f;
|
||||
|
|
@ -2945,10 +2970,9 @@ void LLViewerLODTexture::processTextureStats()
|
|||
//
|
||||
|
||||
S32 current_discard = getDiscardLevel();
|
||||
if (mBoostLevel < LLGLTexture::BOOST_AVATAR_BAKED &&
|
||||
current_discard >= 0)
|
||||
if (mBoostLevel < LLGLTexture::BOOST_AVATAR_BAKED)
|
||||
{
|
||||
if (current_discard < (mDesiredDiscardLevel-1) && !mForceToSaveRawImage)
|
||||
if (current_discard < mDesiredDiscardLevel && !mForceToSaveRawImage)
|
||||
{ // should scale down
|
||||
scaleDown();
|
||||
}
|
||||
|
|
@ -2968,9 +2992,6 @@ void LLViewerLODTexture::processTextureStats()
|
|||
mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel);
|
||||
}
|
||||
|
||||
// decay max virtual size over time
|
||||
mMaxVirtualSize *= 0.8f;
|
||||
|
||||
// selection manager will immediately reset BOOST_SELECTED but never unsets it
|
||||
// unset it immediately after we consume it
|
||||
if (getBoostLevel() == BOOST_SELECTED)
|
||||
|
|
@ -2979,14 +3000,22 @@ void LLViewerLODTexture::processTextureStats()
|
|||
}
|
||||
}
|
||||
|
||||
extern LLGLSLShader gCopyProgram;
|
||||
|
||||
bool LLViewerLODTexture::scaleDown()
|
||||
{
|
||||
if (mGLTexturep.isNull())
|
||||
if (mGLTexturep.isNull() || !mGLTexturep->getHasGLTexture())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return mGLTexturep->scaleDown(mDesiredDiscardLevel);
|
||||
if (!mDownScalePending)
|
||||
{
|
||||
mDownScalePending = true;
|
||||
gTextureList.mDownScaleQueue.push(this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "llmetricperformancetester.h"
|
||||
#include "httpcommon.h"
|
||||
#include "workqueue.h"
|
||||
#include "gltf/common.h"
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
|
@ -102,7 +103,6 @@ public:
|
|||
DYNAMIC_TEXTURE,
|
||||
FETCHED_TEXTURE,
|
||||
LOD_TEXTURE,
|
||||
ATLAS_TEXTURE,
|
||||
INVALID_TEXTURE_TYPE
|
||||
};
|
||||
|
||||
|
|
@ -173,6 +173,15 @@ public:
|
|||
LLViewerMediaTexture* getParcelMedia() const { return mParcelMedia;}
|
||||
|
||||
/*virtual*/ void updateBindStatsForTester() ;
|
||||
|
||||
struct MaterialEntry
|
||||
{
|
||||
S32 mIndex = LL::GLTF::INVALID_INDEX;
|
||||
std::shared_ptr<LL::GLTF::Asset> mAsset;
|
||||
};
|
||||
typedef std::vector<MaterialEntry> material_list_t;
|
||||
material_list_t mMaterialList; // reverse pointer pointing to LL::GLTF::Materials using this image as texture
|
||||
|
||||
protected:
|
||||
void cleanup() ;
|
||||
void init(bool firstinit) ;
|
||||
|
|
@ -214,7 +223,6 @@ public:
|
|||
static S32 sAuxCount;
|
||||
static LLFrameTimer sEvaluationTimer;
|
||||
static F32 sDesiredDiscardBias;
|
||||
static F32 sDesiredDiscardScale;
|
||||
static S32 sMaxSculptRez ;
|
||||
static U32 sMinLargeImageSize ;
|
||||
static U32 sMaxSmallImageSize ;
|
||||
|
|
@ -414,6 +422,9 @@ public:
|
|||
|
||||
/*virtual*/bool isActiveFetching() override; //is actively in fetching by the fetching pipeline.
|
||||
|
||||
bool mCreatePending = false; // if true, this is in gTextureList.mCreateTextureList
|
||||
mutable bool mDownScalePending = false; // if true, this is in gTextureList.mDownScaleQueue
|
||||
|
||||
protected:
|
||||
S32 getCurrentDiscardLevelForFetching() ;
|
||||
void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f);
|
||||
|
|
@ -424,11 +435,6 @@ private:
|
|||
|
||||
void saveRawImage() ;
|
||||
|
||||
//for atlas
|
||||
void resetFaceAtlas() ;
|
||||
void invalidateAtlas(bool rebuild_geom) ;
|
||||
bool insertToAtlas() ;
|
||||
|
||||
private:
|
||||
bool mFullyLoaded;
|
||||
bool mInDebug;
|
||||
|
|
@ -539,9 +545,10 @@ public:
|
|||
/*virtual*/ void processTextureStats();
|
||||
bool isUpdateFrozen() ;
|
||||
|
||||
bool scaleDown();
|
||||
|
||||
private:
|
||||
void init(bool firstinit) ;
|
||||
bool scaleDown() ;
|
||||
|
||||
private:
|
||||
F32 mDiscardVirtualSize; // Virtual size used to calculate desired discard
|
||||
|
|
|
|||
|
|
@ -70,6 +70,8 @@ S32 LLViewerTextureList::sNumImages = 0;
|
|||
|
||||
LLViewerTextureList gTextureList;
|
||||
|
||||
extern LLGLSLShader gCopyProgram;
|
||||
|
||||
ETexListType get_element_type(S32 priority)
|
||||
{
|
||||
return (priority == LLViewerFetchedTexture::BOOST_ICON || priority == LLViewerFetchedTexture::BOOST_THUMBNAIL) ? TEX_LIST_SCALE : TEX_LIST_STANDARD;
|
||||
|
|
@ -352,8 +354,11 @@ void LLViewerTextureList::shutdown()
|
|||
mCallbackList.clear();
|
||||
|
||||
// Flush all of the references
|
||||
mLoadingStreamList.clear();
|
||||
mCreateTextureList.clear();
|
||||
while (!mCreateTextureList.empty())
|
||||
{
|
||||
mCreateTextureList.front()->mCreatePending = false;
|
||||
mCreateTextureList.pop();
|
||||
}
|
||||
mFastCacheList.clear();
|
||||
|
||||
mUUIDMap.clear();
|
||||
|
|
@ -897,14 +902,6 @@ void LLViewerTextureList::clearFetchingRequests()
|
|||
}
|
||||
}
|
||||
|
||||
static void touch_texture(LLViewerFetchedTexture* tex, F32 vsize)
|
||||
{
|
||||
if (tex)
|
||||
{
|
||||
tex->addTextureStats(vsize);
|
||||
}
|
||||
}
|
||||
|
||||
extern bool gCubeSnapshot;
|
||||
|
||||
void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imagep)
|
||||
|
|
@ -921,58 +918,67 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag
|
|||
static LLCachedControl<F32> texture_scale_min(gSavedSettings, "TextureScaleMinAreaFactor", 0.04f);
|
||||
static LLCachedControl<F32> texture_scale_max(gSavedSettings, "TextureScaleMaxAreaFactor", 25.f);
|
||||
|
||||
if (imagep->getType() == LLViewerTexture::LOD_TEXTURE && imagep->getBoostLevel() == LLViewerTexture::BOOST_NONE)
|
||||
{ // reset max virtual size for unboosted LOD_TEXTURES
|
||||
// this is an alternative to decaying mMaxVirtualSize over time
|
||||
// that keeps textures from continously downrezzing and uprezzing in the background
|
||||
imagep->mMaxVirtualSize = 0.f;
|
||||
}
|
||||
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE
|
||||
for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
|
||||
{
|
||||
for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
|
||||
for (S32 fi = 0; fi < imagep->getNumFaces(i); ++fi)
|
||||
{
|
||||
for (S32 fi = 0; fi < imagep->getNumFaces(i); ++fi)
|
||||
LLFace* face = (*(imagep->getFaceList(i)))[fi];
|
||||
|
||||
if (face && face->getViewerObject())
|
||||
{
|
||||
LLFace* face = (*(imagep->getFaceList(i)))[fi];
|
||||
F32 radius;
|
||||
F32 cos_angle_to_view_dir;
|
||||
bool in_frustum = face->calcPixelArea(cos_angle_to_view_dir, radius);
|
||||
static LLCachedControl<F32> bias_unimportant_threshold(gSavedSettings, "TextureBiasUnimportantFactor", 0.25f);
|
||||
F32 vsize = face->getPixelArea();
|
||||
|
||||
if (face && face->getViewerObject() && face->getTextureEntry())
|
||||
{
|
||||
F32 radius;
|
||||
F32 cos_angle_to_view_dir;
|
||||
BOOL in_frustum = face->calcPixelArea(cos_angle_to_view_dir, radius);
|
||||
static LLCachedControl<F32> bias_unimportant_threshold(gSavedSettings, "TextureBiasUnimportantFactor", 0.25f);
|
||||
F32 vsize = face->getPixelArea();
|
||||
// Scale desired texture resolution higher or lower depending on texture scale
|
||||
//
|
||||
// Minimum usage examples: a 1024x1024 texture with aplhabet, runing string
|
||||
// shows one letter at a time
|
||||
//
|
||||
// Maximum usage examples: huge chunk of terrain repeats texture
|
||||
const LLTextureEntry* te = face->getTextureEntry();
|
||||
F32 min_scale = te ? llmin(fabsf(te->getScaleS()), fabsf(te->getScaleT())) : 1.f;
|
||||
min_scale = llclamp(min_scale * min_scale, texture_scale_min(), texture_scale_max());
|
||||
vsize /= min_scale;
|
||||
|
||||
// Scale desired texture resolution higher or lower depending on texture scale
|
||||
//
|
||||
// Minimum usage examples: a 1024x1024 texture with aplhabet, runing string
|
||||
// shows one letter at a time
|
||||
//
|
||||
// Maximum usage examples: huge chunk of terrain repeats texture
|
||||
const LLTextureEntry* te = face->getTextureEntry();
|
||||
F32 min_scale = te ? llmin(fabsf(te->getScaleS()), fabsf(te->getScaleT())) : 1.f;
|
||||
min_scale = llclamp(min_scale*min_scale, texture_scale_min(), texture_scale_max());
|
||||
// if bias is > 2, apply to on-screen textures as well
|
||||
bool apply_bias = LLViewerTexture::sDesiredDiscardBias > 2.f;
|
||||
|
||||
vsize /= min_scale;
|
||||
if (!in_frustum || !face->getDrawable()->isVisible() || face->getImportanceToCamera() < bias_unimportant_threshold)
|
||||
{ // further reduce by discard bias when off screen or occluded
|
||||
vsize /= LLViewerTexture::sDesiredDiscardBias;
|
||||
}
|
||||
// if a GLTF material is present, ignore that face
|
||||
// as far as this texture stats go, but update the GLTF material
|
||||
// stats
|
||||
LLFetchedGLTFMaterial* mat = te ? (LLFetchedGLTFMaterial*)te->getGLTFRenderMaterial() : nullptr;
|
||||
llassert(mat == nullptr || dynamic_cast<LLFetchedGLTFMaterial*>(te->getGLTFRenderMaterial()) != nullptr);
|
||||
if (mat)
|
||||
{
|
||||
touch_texture(mat->mBaseColorTexture, vsize);
|
||||
touch_texture(mat->mNormalTexture, vsize);
|
||||
touch_texture(mat->mMetallicRoughnessTexture, vsize);
|
||||
touch_texture(mat->mEmissiveTexture, vsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
imagep->addTextureStats(vsize);
|
||||
}
|
||||
// apply bias to off screen objects or objects that are small on screen all the time
|
||||
if (!in_frustum || !face->getDrawable()->isVisible() || face->getImportanceToCamera() < bias_unimportant_threshold)
|
||||
{ // further reduce by discard bias when off screen or occluded
|
||||
apply_bias = true;
|
||||
}
|
||||
|
||||
if (apply_bias)
|
||||
{
|
||||
F32 bias = powf(4, LLViewerTexture::sDesiredDiscardBias - 1.f);
|
||||
bias = llround(bias);
|
||||
vsize /= bias;
|
||||
}
|
||||
|
||||
imagep->addTextureStats(vsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make sure to addTextureStats for any spotlights that are using this texture
|
||||
for (S32 vi = 0; vi < imagep->getNumVolumes(LLRender::LIGHT_TEX); ++vi)
|
||||
{
|
||||
LLVOVolume* volume = (*imagep->getVolumeList(LLRender::LIGHT_TEX))[vi];
|
||||
volume->updateSpotLightPriority();
|
||||
}
|
||||
|
||||
//imagep->setDebugText(llformat("%.3f - %d", sqrtf(imagep->getMaxVirtualSize()), imagep->getBoostLevel()));
|
||||
|
||||
F32 lazy_flush_timeout = 30.f; // stop decoding
|
||||
|
|
@ -1066,22 +1072,65 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time)
|
|||
//
|
||||
|
||||
LLTimer create_timer;
|
||||
image_list_t::iterator enditer = mCreateTextureList.begin();
|
||||
for (image_list_t::iterator iter = mCreateTextureList.begin();
|
||||
iter != mCreateTextureList.end();)
|
||||
|
||||
if (!mDownScaleQueue.empty() && gPipeline.mDownResMap.isComplete())
|
||||
{
|
||||
image_list_t::iterator curiter = iter++;
|
||||
enditer = iter;
|
||||
LLViewerFetchedTexture *imagep = *curiter;
|
||||
// just in case we downres textures, bind downresmap and copy program
|
||||
gPipeline.mDownResMap.bindTarget();
|
||||
gCopyProgram.bind();
|
||||
gPipeline.mScreenTriangleVB->setBuffer();
|
||||
|
||||
// give time to downscaling first -- if mDownScaleQueue is not empty, we're running out of memory and need
|
||||
// to free up memory by discarding off screen textures quickly
|
||||
|
||||
// do at least 5 and make sure we don't get too far behind even if it violates
|
||||
// the time limit. If we don't downscale quickly the viewer will hit swap and may
|
||||
// freeze.
|
||||
S32 min_count = (S32)mCreateTextureList.size() / 20 + 5;
|
||||
|
||||
while (!mDownScaleQueue.empty())
|
||||
{
|
||||
LLViewerFetchedTexture* image = mDownScaleQueue.front();
|
||||
llassert(image->mDownScalePending);
|
||||
|
||||
LLImageGL* img = image->getGLTexture();
|
||||
if (img && img->getHasGLTexture())
|
||||
{
|
||||
img->scaleDown(image->getDesiredDiscardLevel());
|
||||
}
|
||||
|
||||
image->mDownScalePending = false;
|
||||
mDownScaleQueue.pop();
|
||||
|
||||
if (create_timer.getElapsedTimeF32() > max_time && --min_count <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gCopyProgram.unbind();
|
||||
gPipeline.mDownResMap.flush();
|
||||
}
|
||||
|
||||
// do at least 5 and make sure we don't get too far behind even if it violates
|
||||
// the time limit. Textures pending creation have a copy of their texture data
|
||||
// in system memory, so we don't want to let them pile up.
|
||||
S32 min_count = (S32) mCreateTextureList.size() / 20 + 5;
|
||||
|
||||
while (!mCreateTextureList.empty())
|
||||
{
|
||||
LLViewerFetchedTexture *imagep = mCreateTextureList.front();
|
||||
llassert(imagep->mCreatePending);
|
||||
imagep->createTexture();
|
||||
imagep->postCreateTexture();
|
||||
imagep->mCreatePending = false;
|
||||
mCreateTextureList.pop();
|
||||
|
||||
if (create_timer.getElapsedTimeF32() > max_time)
|
||||
if (create_timer.getElapsedTimeF32() > max_time && --min_count <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
mCreateTextureList.erase(mCreateTextureList.begin(), enditer);
|
||||
return create_timer.getElapsedTimeF32();
|
||||
}
|
||||
|
||||
|
|
@ -1124,7 +1173,10 @@ void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep)
|
|||
removeImageFromList(imagep);
|
||||
}
|
||||
|
||||
imagep->processTextureStats();
|
||||
if (!gCubeSnapshot)
|
||||
{ // never call processTextureStats in a cube snapshot
|
||||
imagep->processTextureStats();
|
||||
}
|
||||
imagep->sMaxVirtualSize = LLViewerFetchedTexture::sMaxVirtualSize;
|
||||
addImageToList(imagep);
|
||||
|
||||
|
|
@ -1134,6 +1186,7 @@ void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep)
|
|||
F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
|
||||
|
||||
typedef std::vector<LLPointer<LLViewerFetchedTexture> > entries_list_t;
|
||||
entries_list_t entries;
|
||||
|
||||
|
|
|
|||
|
|
@ -144,12 +144,13 @@ public:
|
|||
void clearFetchingRequests();
|
||||
void setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level);
|
||||
|
||||
private:
|
||||
// do some book keeping on the specified texture
|
||||
// - updates decode priority
|
||||
// - updates desired discard level
|
||||
// - cleans up textures that haven't been referenced in awhile
|
||||
void updateImageDecodePriority(LLViewerFetchedTexture* imagep);
|
||||
|
||||
private:
|
||||
F32 updateImagesCreateTextures(F32 max_time);
|
||||
F32 updateImagesFetchTextures(F32 max_time);
|
||||
void updateImagesUpdateStats();
|
||||
|
|
@ -211,8 +212,14 @@ private:
|
|||
|
||||
public:
|
||||
typedef std::unordered_set<LLPointer<LLViewerFetchedTexture> > image_list_t;
|
||||
image_list_t mLoadingStreamList;
|
||||
image_list_t mCreateTextureList;
|
||||
typedef std::queue<LLPointer<LLViewerFetchedTexture> > image_queue_t;
|
||||
|
||||
// images that have been loaded but are waiting to be uploaded to GL
|
||||
image_queue_t mCreateTextureList;
|
||||
|
||||
// images that must be downscaled quickly so we don't run out of memory
|
||||
image_queue_t mDownScaleQueue;
|
||||
|
||||
image_list_t mCallbackList;
|
||||
image_list_t mFastCacheList;
|
||||
|
||||
|
|
|
|||
|
|
@ -451,6 +451,9 @@ void LLVOGrass::plantBlades()
|
|||
face->setVertexBuffer(NULL);
|
||||
face->setTEOffset(0);
|
||||
face->mCenterLocal = mPosition + mRegionp->getOriginAgent();
|
||||
const LLVector4a* ext = mDrawable->getSpatialExtents();
|
||||
face->mExtents[0] = ext[0];
|
||||
face->mExtents[1] = ext[1];
|
||||
}
|
||||
|
||||
mDepth = (face->mCenterLocal - LLViewerCamera::getInstance()->getOrigin())*LLViewerCamera::getInstance()->getAtAxis();
|
||||
|
|
|
|||
|
|
@ -461,9 +461,7 @@ void LLVOTree::updateTextures()
|
|||
{
|
||||
setDebugText(llformat("%4.0f", (F32) sqrt(mPixelArea)));
|
||||
}
|
||||
mTreeImagep->addTextureStats(mPixelArea);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -479,7 +477,7 @@ LLDrawable* LLVOTree::createDrawable(LLPipeline *pipeline)
|
|||
// Just a placeholder for an actual object...
|
||||
LLFace *facep = mDrawable->addFace(poolp, mTreeImagep);
|
||||
facep->setSize(1, 3);
|
||||
|
||||
facep->setTexture(LLRender::DIFFUSE_MAP, mTreeImagep);
|
||||
updateRadius();
|
||||
|
||||
return mDrawable;
|
||||
|
|
@ -1169,6 +1167,10 @@ void LLVOTree::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
|
|||
LLVector4a pos;
|
||||
pos.load3(center.mV);
|
||||
mDrawable->setPositionGroup(pos);
|
||||
|
||||
LLFace* facep = mDrawable->getFace(0);
|
||||
facep->mExtents[0] = newMin;
|
||||
facep->mExtents[1] = newMax;
|
||||
}
|
||||
|
||||
bool LLVOTree::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, bool pick_transparent, bool pick_rigged, bool pick_unselectable, S32 *face_hitp,
|
||||
|
|
|
|||
|
|
@ -5745,18 +5745,23 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||
{
|
||||
continue;
|
||||
}
|
||||
#if 0
|
||||
#if LL_RELEASE_WITH_DEBUG_INFO
|
||||
const LLUUID pbr_id( "49c88210-7238-2a6b-70ac-92d4f35963cf" );
|
||||
const LLUUID obj_id( vobj->getID() );
|
||||
bool is_pbr = (obj_id == pbr_id);
|
||||
#else
|
||||
bool is_pbr = false;
|
||||
#endif
|
||||
#else
|
||||
LLGLTFMaterial *gltf_mat = facep->getTextureEntry()->getGLTFRenderMaterial();
|
||||
|
||||
LLFetchedGLTFMaterial *gltf_mat = (LLFetchedGLTFMaterial*) facep->getTextureEntry()->getGLTFRenderMaterial();
|
||||
bool is_pbr = gltf_mat != nullptr;
|
||||
#endif
|
||||
|
||||
if (is_pbr)
|
||||
{
|
||||
// tell texture streaming system to ignore blinn-phong textures
|
||||
facep->setTexture(LLRender::DIFFUSE_MAP, nullptr);
|
||||
facep->setTexture(LLRender::NORMAL_MAP, nullptr);
|
||||
facep->setTexture(LLRender::SPECULAR_MAP, nullptr);
|
||||
|
||||
// let texture streaming system know about PBR textures
|
||||
facep->setTexture(LLRender::BASECOLOR_MAP, gltf_mat->mBaseColorTexture);
|
||||
facep->setTexture(LLRender::GLTF_NORMAL_MAP, gltf_mat->mNormalTexture);
|
||||
facep->setTexture(LLRender::METALLIC_ROUGHNESS_MAP, gltf_mat->mMetallicRoughnessTexture);
|
||||
facep->setTexture(LLRender::EMISSIVE_MAP, gltf_mat->mEmissiveTexture);
|
||||
}
|
||||
|
||||
//ALWAYS null out vertex buffer on rebuild -- if the face lands in a render
|
||||
// batch, it will recover its vertex buffer reference from the spatial group
|
||||
|
|
|
|||
|
|
@ -865,6 +865,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
|
|||
const U32 post_color_fmt = post_hdr ? GL_RGBA16F : GL_RGBA;
|
||||
mPostMap.allocate(resX, resY, post_color_fmt);
|
||||
|
||||
// used to scale down textures
|
||||
// See LLViwerTextureList::updateImagesCreateTextures and LLImageGL::scaleDown
|
||||
mDownResMap.allocate(4, 4, GL_RGBA);
|
||||
|
||||
//HACK make screenbuffer allocations start failing after 30 seconds
|
||||
if (gSavedSettings.getBOOL("SimulateFBOFailure"))
|
||||
{
|
||||
|
|
@ -1111,6 +1115,8 @@ void LLPipeline::releaseGLBuffers()
|
|||
|
||||
mPostMap.release();
|
||||
|
||||
mDownResMap.release();
|
||||
|
||||
for (U32 i = 0; i < 3; i++)
|
||||
{
|
||||
mGlow[i].release();
|
||||
|
|
|
|||
|
|
@ -725,6 +725,9 @@ public:
|
|||
// tonemapped and gamma corrected render ready for post
|
||||
LLRenderTarget mPostMap;
|
||||
|
||||
// downres scratch space for GPU downscaling of textures
|
||||
LLRenderTarget mDownResMap;
|
||||
|
||||
LLCullResult mSky;
|
||||
LLCullResult mReflectedObjects;
|
||||
LLCullResult mRefractedObjects;
|
||||
|
|
|
|||
Loading…
Reference in New Issue