# Conflicts:
#	indra/llfilesystem/llfilesystem.cpp
#	indra/newview/llappviewer.cpp
#	indra/newview/lltextureview.cpp
#	indra/newview/llviewertexture.h
#	indra/newview/llviewertexturelist.cpp
master
Ansariel 2024-07-06 11:06:55 +02:00
commit e9b6550c48
38 changed files with 566 additions and 192 deletions

View File

@ -0,0 +1,12 @@
# PBR Materials
## KHR Texture Transforms
Texture repeats for PBR materials on prims are based on the [KHR\_texture\_transform](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform) spec, and thus should be expected to behave according to the spec. We currently suport offset, rotation, and scale from the spec. texCoord is not currently supported.
PBR materials should have approximately correct lighting based on the normal texture:
- With default texture transforms, assuming the prim or model has correct normals and tangents
- With a texture transform applied, especially rotation or negative scale
- With a texture animation applied via `llSetTextureAnim`, especially a rotation animation
- Note: Texture animations are not guaranteed to loop when a PBR texture transform is applied

View File

@ -39,7 +39,7 @@ PBR terrain does not support materials with alpha blend or double-sided. In addi
## PBR Terrain Texture Transforms ## PBR Terrain Texture Transforms
Like PBR materials on prims, PBR terrain repeats are based on the [KHR\_texture\_transform](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform) spec, and thus should be expected to behave the same way. Like PBR materials on prims, PBR terrain repeats are based on the [KHR\_texture\_transform](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform) spec, and thus should be expected to behave the same way. We currently suport offset, rotation, and scale from the spec. texCoord is not currently supported.
The southwest corner of a region, at z=0, is the UV origin for all texture coordinates of the whole region. Unless an offset is also applied, scale and rotation of the terrain texture transforms are relative to that point. The southwest corner of a region, at z=0, is the UV origin for all texture coordinates of the whole region. Unless an offset is also applied, scale and rotation of the terrain texture transforms are relative to that point.

View File

@ -87,6 +87,12 @@ If saving the terrain fails for any reason, the terrain should not be updated.
Unlike a viewer without PBR terrain support, the new viewer will no longer treat textures with alpha channels as invalid. Unlike a viewer without PBR terrain support, the new viewer will no longer treat textures with alpha channels as invalid.
### Saving PBR Terrain Texture Transforms
If "PBR Metallic Roughness" checkbox is checked, a user with saving composition permissions should also be allowed to edit and save PBR texture transforms.
One texture transform may be set for each material swatch. Setting texture transforms for each individual texture on the material is not currently supported.
## Graphics Features ## Graphics Features
Texture terrain with transparency is not permitted to be applied in the viewer. Texture terrain with transparency is not permitted to be applied in the viewer.

View File

@ -79,7 +79,7 @@ LLFileSystem::~LLFileSystem()
// static // static
bool LLFileSystem::getExists(const LLUUID& file_id, const LLAssetType::EType file_type) bool LLFileSystem::getExists(const LLUUID& file_id, const LLAssetType::EType file_type)
{ {
LL_PROFILE_ZONE_COLOR(tracy::Color::Gold); // <FS:Beq> measure cache performance LL_PROFILE_ZONE_SCOPED;
std::string id_str; std::string id_str;
file_id.toString(id_str); file_id.toString(id_str);
const std::string extra_info = ""; const std::string extra_info = "";

View File

@ -484,6 +484,8 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
void *user_data, void *user_data,
bool is_priority) bool is_priority)
{ {
LL_PROFILE_ZONE_SCOPED;
LL_DEBUGS("AssetStorage") << "LLAssetStorage::getAssetData() - " << uuid << "," << LLAssetType::lookup(type) << LL_ENDL; LL_DEBUGS("AssetStorage") << "LLAssetStorage::getAssetData() - " << uuid << "," << LLAssetType::lookup(type) << LL_ENDL;
LL_DEBUGS("AssetStorage") << "ASSET_TRACE requesting " << uuid << " type " << 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) if (size > 0)
{ {
LL_PROFILE_ZONE_NAMED("gad - file in cache");
// we've already got the file // we've already got the file
// theoretically, partial files w/o a pending request shouldn't happen // theoretically, partial files w/o a pending request shouldn't happen
// unless there's a weird error // unless there's a weird error
@ -548,7 +551,7 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
} }
bool duplicate = false; bool duplicate = false;
LL_PROFILE_ZONE_NAMED("gad - check pending downloads");
// check to see if there's a pending download of this uuid already // check to see if there's a pending download of this uuid already
for (request_list_t::iterator iter = mPendingDownloads.begin(); for (request_list_t::iterator iter = mPendingDownloads.begin();
iter != mPendingDownloads.end(); ++iter ) iter != mPendingDownloads.end(); ++iter )

View File

@ -116,6 +116,9 @@ public:
bool mIsNVIDIA; bool mIsNVIDIA;
bool mIsIntel; bool mIsIntel;
// hints to the render pipe
U32 mDownScaleMethod = 0; // see settings.xml RenderDownScaleMethod
#if LL_DARWIN #if LL_DARWIN
// Needed to distinguish problem cards on older Macs that break with Materials // Needed to distinguish problem cards on older Macs that break with Materials
bool mIsMobileGF; bool mIsMobileGF;

View File

@ -57,6 +57,9 @@ const F32 MIN_TEXTURE_LIFETIME = 10.f;
U32 wpo2(U32 i); U32 wpo2(U32 i);
U32 LLImageGL::sFrameCount = 0;
// texture memory accounting (for macOS) // texture memory accounting (for macOS)
static LLMutex sTexMemMutex; static LLMutex sTexMemMutex;
static std::unordered_map<U32, U64> sTextureAllocs; static std::unordered_map<U32, U64> sTextureAllocs;
@ -1003,7 +1006,7 @@ bool should_stagger_image_set(bool compressed)
#else #else
// glTexSubImage2D doesn't work with compressed textures on select tested Nvidia GPUs on Windows 10 -Cosmic,2023-03-08 // 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 // 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 #endif
} }
@ -1185,13 +1188,37 @@ void LLImageGL::generateTextures(S32 numTextures, U32 *textures)
} }
} }
// static
void LLImageGL::updateClass()
{
sFrameCount++;
}
// static // static
void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures) 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) if (gGLManager.mInited)
{ {
free_tex_images(numTextures, textures); LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
glDeleteTextures(numTextures, textures); 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);
}
} }
} }
@ -2338,10 +2365,50 @@ bool LLImageGL::scaleDown(S32 desired_discard)
S32 desired_width = getWidth(desired_discard); S32 desired_width = getWidth(desired_discard);
S32 desired_height = getHeight(desired_discard); S32 desired_height = getHeight(desired_discard);
U64 size = getBytes(desired_discard); if (gGLManager.mDownScaleMethod == 0)
llassert(size <= 2048*2048*4); // we shouldn't be using this method to downscale huge textures, but it'll work { // use an FBO to downscale the texture
gGL.getTexUnit(0)->bind(this); // 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);
// 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);
if (sScratchPBO == 0) if (sScratchPBO == 0)
{ {
@ -2376,6 +2443,7 @@ bool LLImageGL::scaleDown(S32 desired_discard)
} }
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
mCurrentDiscardLevel = desired_discard; mCurrentDiscardLevel = desired_discard;

View File

@ -62,6 +62,9 @@ class LLImageGL : public LLRefCount
friend class LLTexUnit; friend class LLTexUnit;
public: public:
// call once per frame
static void updateClass();
// Get an estimate of how many bytes have been allocated in vram for textures. // Get an estimate of how many bytes have been allocated in vram for textures.
// Does not include mipmaps. // Does not include mipmaps.
// NOTE: multiplying this number by two gives a good estimate for total // NOTE: multiplying this number by two gives a good estimate for total
@ -279,7 +282,7 @@ protected:
public: public:
static std::unordered_set<LLImageGL*> sImageList; static std::unordered_set<LLImageGL*> sImageList;
static S32 sCount; static S32 sCount;
static U32 sFrameCount;
static F32 sLastFrameTime; static F32 sLastFrameTime;
// Global memory statistics // Global memory statistics

View File

@ -307,7 +307,11 @@ public:
ALTERNATE_DIFFUSE_MAP = 1, ALTERNATE_DIFFUSE_MAP = 1,
NORMAL_MAP = 1, NORMAL_MAP = 1,
SPECULAR_MAP = 2, 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 enum eVolumeTexIndex : U8

View File

@ -426,14 +426,17 @@ void LLRenderTarget::bindTarget()
GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT2,
GL_COLOR_ATTACHMENT3}; GL_COLOR_ATTACHMENT3};
glDrawBuffers(static_cast<GLsizei>(mTex.size()), drawbuffers);
if (mTex.empty()) if (mTex.empty())
{ //no color buffer to draw to { //no color buffer to draw to
glDrawBuffer(GL_NONE); glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE); glReadBuffer(GL_NONE);
} }
else
{
glDrawBuffers(static_cast<GLsizei>(mTex.size()), drawbuffers);
glReadBuffer(GL_COLOR_ATTACHMENT0);
}
check_framebuffer_status(); check_framebuffer_status();
glViewport(0, 0, mResX, mResY); glViewport(0, 0, mResX, mResY);
@ -519,7 +522,8 @@ void LLRenderTarget::flush()
llassert(sCurFBO == mFBO); llassert(sCurFBO == mFBO);
llassert(sBoundTarget == this); llassert(sBoundTarget == this);
if (mGenerateMipMaps == LLTexUnit::TMG_AUTO) { if (mGenerateMipMaps == LLTexUnit::TMG_AUTO)
{
LL_PROFILE_GPU_ZONE("rt generate mipmaps"); LL_PROFILE_GPU_ZONE("rt generate mipmaps");
bindTexture(0, 0, LLTexUnit::TFO_TRILINEAR); bindTexture(0, 0, LLTexUnit::TFO_TRILINEAR);
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
@ -540,6 +544,8 @@ void LLRenderTarget::flush()
glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
sCurResX = gGLViewport[2]; sCurResX = gGLViewport[2];
sCurResY = gGLViewport[3]; sCurResY = gGLViewport[3];
glReadBuffer(GL_BACK);
glDrawBuffer(GL_BACK);
} }
} }

View File

@ -172,6 +172,8 @@ public:
// *HACK // *HACK
void swapFBORefs(LLRenderTarget& other); void swapFBORefs(LLRenderTarget& other);
static LLRenderTarget* sBoundTarget;
protected: protected:
U32 mResX; U32 mResX;
U32 mResY; U32 mResY;
@ -186,8 +188,6 @@ protected:
U32 mMipLevels; U32 mMipLevels;
LLTexUnit::eTextureType mUsage; LLTexUnit::eTextureType mUsage;
static LLRenderTarget* sBoundTarget;
}; };
#endif #endif

View File

@ -11145,7 +11145,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Comment</key> <key>Comment</key>
<string>Minimum of available physical memory in MB before textures get scaled down</string> <string>Minimum of available physical memory in MB before textures get scaled down</string>
<key>Persist</key> <key>Persist</key>
<integer>1</integer> <integer>0</integer>
<key>Type</key> <key>Type</key>
<string>U32</string> <string>U32</string>
<key>Value</key> <key>Value</key>
@ -11183,6 +11183,17 @@ Change of this parameter will affect the layout of buttons in notification toast
<string>U32</string> <string>U32</string>
<key>Value</key> <key>Value</key>
<integer>2048</integer> <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> </map>
<key>RenderDebugTextureBind</key> <key>RenderDebugTextureBind</key>
<map> <map>

View File

@ -1,4 +1,4 @@
version 60 version 61
// The version number above should be incremented IF AND ONLY IF some // The version number above should be incremented IF AND ONLY IF some
// change has been made that is sufficiently important to justify // change has been made that is sufficiently important to justify
// resetting the graphics preferences of all users to the recommended // resetting the graphics preferences of all users to the recommended
@ -76,6 +76,7 @@ RenderGLMultiThreadedMedia 1 1
RenderReflectionProbeResolution 1 128 RenderReflectionProbeResolution 1 128
RenderScreenSpaceReflections 1 1 RenderScreenSpaceReflections 1 1
RenderMirrors 1 1 RenderMirrors 1 1
RenderDownScaleMethod 1 1
// //
@ -366,6 +367,7 @@ RenderAnisotropic 1 0
RenderFSAASamples 1 0 RenderFSAASamples 1 0
RenderGLContextCoreProfile 1 0 RenderGLContextCoreProfile 1 0
RenderGLMultiThreadedMedia 1 0 RenderGLMultiThreadedMedia 1 0
RenderDownScaleMethod 1 0
list AMD list AMD
RenderGLMultiThreadedTextures 1 1 RenderGLMultiThreadedTextures 1 1

View File

@ -1,4 +1,4 @@
version 47 version 48
// The version number above should be incremented IF AND ONLY IF some // The version number above should be incremented IF AND ONLY IF some
// change has been made that is sufficiently important to justify // change has been made that is sufficiently important to justify
// resetting the graphics preferences of all users to the recommended // resetting the graphics preferences of all users to the recommended
@ -75,6 +75,8 @@ RenderGLMultiThreadedTextures 1 0
RenderGLMultiThreadedMedia 1 1 RenderGLMultiThreadedMedia 1 1
RenderReflectionProbeResolution 1 128 RenderReflectionProbeResolution 1 128
RenderScreenSpaceReflections 1 1 RenderScreenSpaceReflections 1 1
RenderMirrors 1 1
RenderDownScaleMethod 1 1
// //
@ -110,7 +112,7 @@ RenderReflectionProbeLevel 1 0
RenderMirrors 1 0 RenderMirrors 1 0
RenderHeroProbeResolution 1 256 RenderHeroProbeResolution 1 256
RenderHeroProbeDistance 1 4 RenderHeroProbeDistance 1 4
RenderHeroProbeUpdateRate 1 4 RenderHeroProbeUpdateRate 1 6
RenderHeroProbeConservativeUpdateMultiplier 1 16 RenderHeroProbeConservativeUpdateMultiplier 1 16
// //
@ -251,8 +253,8 @@ RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 1 RenderReflectionProbeDetail 1 1
RenderScreenSpaceReflections 1 0 RenderScreenSpaceReflections 1 0
RenderReflectionProbeLevel 1 3 RenderReflectionProbeLevel 1 3
RenderMirrors 1 0 RenderMirrors 1 1
RenderHeroProbeResolution 1 1024 RenderHeroProbeResolution 1 512
RenderHeroProbeDistance 1 8 RenderHeroProbeDistance 1 8
RenderHeroProbeUpdateRate 1 2 RenderHeroProbeUpdateRate 1 2
RenderHeroProbeConservativeUpdateMultiplier 1 8 RenderHeroProbeConservativeUpdateMultiplier 1 8
@ -287,7 +289,7 @@ RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 1 RenderReflectionProbeDetail 1 1
RenderScreenSpaceReflections 1 0 RenderScreenSpaceReflections 1 0
RenderReflectionProbeLevel 1 3 RenderReflectionProbeLevel 1 3
RenderMirrors 1 0 RenderMirrors 1 1
RenderHeroProbeResolution 1 1024 RenderHeroProbeResolution 1 1024
RenderHeroProbeDistance 1 16 RenderHeroProbeDistance 1 16
RenderHeroProbeUpdateRate 1 1 RenderHeroProbeUpdateRate 1 1
@ -367,13 +369,12 @@ RenderCubeMap 0 0
RenderFSAASamples 1 0 RenderFSAASamples 1 0
RenderGLContextCoreProfile 1 0 RenderGLContextCoreProfile 1 0
RenderGLMultiThreadedMedia 1 0 RenderGLMultiThreadedMedia 1 0
RenderDownScaleMethod 1 0
// AMD cards generally perform better when not using VBOs for streaming data // AMD cards generally perform better when not using VBOs for streaming data
// AMD cards also prefer an OpenGL Compatibility Profile Context // AMD cards also prefer an OpenGL Compatibility Profile Context
list AMD list AMD
RenderGLMultiThreadedTextures 1 1 RenderGLMultiThreadedTextures 1 1
RenderUseStreamVBO 1 0
RenderGLContextCoreProfile 1 0
list GL3 list GL3
RenderFSAASamples 0 0 RenderFSAASamples 0 0

View File

@ -36,8 +36,6 @@ namespace LL
{ {
namespace GLTF namespace GLTF
{ {
constexpr S32 INVALID_INDEX = -1;
class Buffer class Buffer
{ {
public: public:

View File

@ -476,6 +476,7 @@ void Asset::update()
{ // HACK - force texture to be loaded full rez { // HACK - force texture to be loaded full rez
// TODO: calculate actual vsize // TODO: calculate actual vsize
image.mTexture->addTextureStats(2048.f * 2048.f); image.mTexture->addTextureStats(2048.f * 2048.f);
image.mTexture->setBoostLevel(LLViewerTexture::BOOST_HIGH);
} }
} }
} }

View File

@ -43,6 +43,8 @@ namespace LL
{ {
namespace GLTF namespace GLTF
{ {
constexpr S32 INVALID_INDEX = -1;
using Value = boost::json::value; using Value = boost::json::value;
using mat4 = glm::mat4; using mat4 = glm::mat4;

View File

@ -345,6 +345,12 @@ void GLTFSceneManager::addGLTFObject(LLViewerObject* obj, LLUUID gltf_id)
llassert(obj->getVolume()->getParams().getSculptID() == gltf_id); llassert(obj->getVolume()->getParams().getSculptID() == gltf_id);
llassert(obj->getVolume()->getParams().getSculptType() == LL_SCULPT_TYPE_GLTF); 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(); obj->ref();
gAssetStorage->getAssetData(gltf_id, LLAssetType::AT_GLTF, onGLTFLoadComplete, obj); gAssetStorage->getAssetData(gltf_id, LLAssetType::AT_GLTF, onGLTFLoadComplete, obj);
} }

View File

@ -2593,8 +2593,8 @@ bool LLAppViewer::initThreads()
// The viewer typically starts around 8 threads not including image decode, // The viewer typically starts around 8 threads not including image decode,
// so try to leave at least one core free // so try to leave at least one core free
// <FS:Ansariel> Override image decode thread config // <FS:Ansariel> Override image decode thread config
//S32 image_decode_count = llclamp(cores - 9, 1, 8); //S32 image_decode_count = llclamp(cores - 6, 2, 16);
S32 image_decode_count = llclamp(cores - 4, 1, 8); S32 image_decode_count = llclamp(cores - 4, 2, 8);
if (auto max_decodes = gSavedSettings.getU32("FSImageDecodeThreads"); max_decodes > 0) if (auto max_decodes = gSavedSettings.getU32("FSImageDecodeThreads"); max_decodes > 0)
{ {
image_decode_count = llclamp((S32)max_decodes, 1, 32); image_decode_count = llclamp((S32)max_decodes, 1, 32);
@ -5463,6 +5463,10 @@ void LLAppViewer::idle()
LLGLTFMaterialList::flushUpdates(); 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. // Service the WorkQueue we use for replies from worker threads.
// Use function statics for the timeslice setting so we only have to fetch // Use function statics for the timeslice setting so we only have to fetch
// and convert MainWorkTime once. // and convert MainWorkTime once.

View File

@ -82,10 +82,6 @@ LLDrawPoolAlpha::~LLDrawPoolAlpha()
void LLDrawPoolAlpha::prerender() void LLDrawPoolAlpha::prerender()
{ {
mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); 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() S32 LLDrawPoolAlpha::getNumPostDeferredPasses()

View File

@ -173,6 +173,8 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
mImportanceToCamera = 0.f ; mImportanceToCamera = 0.f ;
mBoundingSphereRadius = 0.0f ; mBoundingSphereRadius = 0.0f ;
mTexExtents[0].set(0, 0);
mTexExtents[1].set(1, 1);
mHasMedia = false ; mHasMedia = false ;
mIsMediaAllowed = true; mIsMediaAllowed = true;
@ -2181,10 +2183,12 @@ void LLFace::resetVirtualSize()
F32 LLFace::getTextureVirtualSize() F32 LLFace::getTextureVirtualSize()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
F32 radius; F32 radius;
F32 cos_angle_to_view_dir; F32 cos_angle_to_view_dir;
bool in_frustum = calcPixelArea(cos_angle_to_view_dir, radius); bool in_frustum = calcPixelArea(cos_angle_to_view_dir, radius);
if (mPixelArea < F_ALMOST_ZERO || !in_frustum) if (mPixelArea < F_ALMOST_ZERO || !in_frustum)
{ {
setVirtualSize(0.f) ; setVirtualSize(0.f) ;

View File

@ -866,8 +866,7 @@ void LLFloaterEmojiPicker::createEmojiIcon(const LLEmojiSearchResult& emoji,
void LLFloaterEmojiPicker::showPreview(bool show) void LLFloaterEmojiPicker::showPreview(bool show)
{ {
//mPreview->setIcon(nullptr); mDummy->setVisible(!show);
mDummy->setVisible(show);
mPreview->setVisible(show); mPreview->setVisible(show);
} }

View File

@ -52,8 +52,6 @@ LLFloaterGLTFAssetEditor::LLFloaterGLTFAssetEditor(const LLSD& key)
LLFloaterGLTFAssetEditor::~LLFloaterGLTFAssetEditor() LLFloaterGLTFAssetEditor::~LLFloaterGLTFAssetEditor()
{ {
gIdleCallbacks.deleteFunction(idle, this);
if (mScroller) if (mScroller)
{ {
removeChild(mScroller); removeChild(mScroller);
@ -120,7 +118,7 @@ void LLFloaterGLTFAssetEditor::initFolderRoot()
// Insert that scroller into the panel widgets hierarchy // Insert that scroller into the panel widgets hierarchy
mItemListPanel->addChild(mScroller); mItemListPanel->addChild(mScroller);
// Create the root model and view for all conversation sessions // Create the root model
LLGLTFFolderItem* base_item = new LLGLTFFolderItem(mGLTFViewModel); LLGLTFFolderItem* base_item = new LLGLTFFolderItem(mGLTFViewModel);
LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>()); LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>());
@ -144,15 +142,32 @@ void LLFloaterGLTFAssetEditor::initFolderRoot()
mFolderRoot->setOpen(true); mFolderRoot->setOpen(true);
mFolderRoot->setSelectCallback([this](const std::deque<LLFolderViewItem*>& items, bool user_action) { onFolderSelectionChanged(items, user_action); }); mFolderRoot->setSelectCallback([this](const std::deque<LLFolderViewItem*>& items, bool user_action) { onFolderSelectionChanged(items, user_action); });
mScroller->setVisible(true); mScroller->setVisible(true);
gIdleCallbacks.addFunction(idle, this);
} }
void LLFloaterGLTFAssetEditor::onOpen(const LLSD& key) void LLFloaterGLTFAssetEditor::onOpen(const LLSD& key)
{ {
gIdleCallbacks.addFunction(idle, this);
loadFromSelection(); loadFromSelection();
} }
void LLFloaterGLTFAssetEditor::onClose(bool app_quitting)
{
gIdleCallbacks.deleteFunction(idle, this);
mAsset = nullptr;
mObject = nullptr;
}
void LLFloaterGLTFAssetEditor::clearRoot()
{
LLFolderViewFolder::folders_t::iterator folders_it = mFolderRoot->getFoldersBegin();
while (folders_it != mFolderRoot->getFoldersEnd())
{
(*folders_it)->destroyView();
folders_it = mFolderRoot->getFoldersBegin();
}
mNodeToItemMap.clear();
}
void LLFloaterGLTFAssetEditor::idle(void* user_data) void LLFloaterGLTFAssetEditor::idle(void* user_data)
{ {
LLFloaterGLTFAssetEditor* floater = (LLFloaterGLTFAssetEditor*)user_data; LLFloaterGLTFAssetEditor* floater = (LLFloaterGLTFAssetEditor*)user_data;
@ -216,6 +231,8 @@ void LLFloaterGLTFAssetEditor::loadFromNode(S32 node_id, LLFolderViewFolder* par
view->setVisible(true); view->setVisible(true);
view->setOpen(true); view->setOpen(true);
mNodeToItemMap[node_id] = view;
for (S32& node_id : node.mChildren) for (S32& node_id : node.mChildren)
{ {
loadFromNode(node_id, view); loadFromNode(node_id, view);
@ -246,8 +263,12 @@ void LLFloaterGLTFAssetEditor::loadFromNode(S32 node_id, LLFolderViewFolder* par
void LLFloaterGLTFAssetEditor::loadFromSelection() void LLFloaterGLTFAssetEditor::loadFromSelection()
{ {
if (!mFolderRoot || LLSelectMgr::getInstance()->getSelection()->getObjectCount() != 1) clearRoot();
if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() != 1)
{ {
mAsset = nullptr;
mObject = nullptr;
return; return;
} }
@ -255,14 +276,19 @@ void LLFloaterGLTFAssetEditor::loadFromSelection()
LLViewerObject* objectp = node->getObject(); LLViewerObject* objectp = node->getObject();
if (!objectp) if (!objectp)
{ {
mAsset = nullptr;
mObject = nullptr;
return; return;
} }
mAsset = objectp->mGLTFAsset; if (!objectp->mGLTFAsset)
if (!mAsset)
{ {
mAsset = nullptr;
mObject = nullptr;
return; return;
} }
mAsset = objectp->mGLTFAsset;
mObject = objectp;
if (node->mName.empty()) if (node->mName.empty())
{ {
@ -289,7 +315,6 @@ void LLFloaterGLTFAssetEditor::loadFromSelection()
LLGLTFFolderItem* listener = new LLGLTFFolderItem(i, name, LLGLTFFolderItem::TYPE_SCENE, mGLTFViewModel); LLGLTFFolderItem* listener = new LLGLTFFolderItem(i, name, LLGLTFFolderItem::TYPE_SCENE, mGLTFViewModel);
LLFolderViewFolder::Params p; LLFolderViewFolder::Params p;
p.name = name; p.name = name;
p.root = mFolderRoot; p.root = mFolderRoot;
@ -316,6 +341,50 @@ void LLFloaterGLTFAssetEditor::loadFromSelection()
mFolderRoot->update(); mFolderRoot->update();
} }
void LLFloaterGLTFAssetEditor::dirty()
{
if (!mObject || !mAsset || !mFolderRoot)
{
closeFloater();
return;
}
if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() > 1)
{
closeFloater();
return;
}
LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(NULL);
if (!node)
{
// not yet updated?
// Todo: Subscribe to deletion in some way
return;
}
LLViewerObject* objectp = node->getObject();
if (mObject != objectp || !objectp->mGLTFAsset)
{
closeFloater();
return;
}
if (mAsset != objectp->mGLTFAsset)
{
loadFromSelection();
return;
}
auto found = mNodeToItemMap.find(node->mSelectedGLTFNode);
if (found != mNodeToItemMap.end())
{
LLFolderViewItem* itemp = found->second;
itemp->arrangeAndSet(true, false);
loadNodeTransforms(node->mSelectedGLTFNode);
}
}
void LLFloaterGLTFAssetEditor::onFolderSelectionChanged(const std::deque<LLFolderViewItem*>& items, bool user_action) void LLFloaterGLTFAssetEditor::onFolderSelectionChanged(const std::deque<LLFolderViewItem*>& items, bool user_action)
{ {
if (items.empty()) if (items.empty())
@ -329,10 +398,30 @@ void LLFloaterGLTFAssetEditor::onFolderSelectionChanged(const std::deque<LLFolde
switch (vmi->getType()) switch (vmi->getType())
{ {
case LLGLTFFolderItem::TYPE_SCENE:
{
setTransformsEnabled(false);
LLSelectMgr::getInstance()->selectObjectOnly(mObject, SELECT_ALL_TES, -1, -1);
break;
}
case LLGLTFFolderItem::TYPE_NODE: case LLGLTFFolderItem::TYPE_NODE:
{ {
setTransformsEnabled(true); setTransformsEnabled(true);
loadNodeTransforms(vmi->getItemId()); loadNodeTransforms(vmi->getItemId());
LLSelectMgr::getInstance()->selectObjectOnly(mObject, SELECT_ALL_TES, vmi->getItemId(), 0);
break;
}
case LLGLTFFolderItem::TYPE_MESH:
case LLGLTFFolderItem::TYPE_SKIN:
{
if (item->getParent()) // should be a node
{
LLFolderViewFolder* parent = item->getParentFolder();
LLGLTFFolderItem* parent_vmi = static_cast<LLGLTFFolderItem*>(parent->getViewModelItem());
LLSelectMgr::getInstance()->selectObjectOnly(mObject, SELECT_ALL_TES, parent_vmi->getItemId(), 0);
}
setTransformsEnabled(false);
break; break;
} }
default: default:
@ -368,6 +457,7 @@ void LLFloaterGLTFAssetEditor::loadNodeTransforms(S32 node_id)
} }
LL::GLTF::Node& node = mAsset->mNodes[node_id]; LL::GLTF::Node& node = mAsset->mNodes[node_id];
node.makeTRSValid();
mCtrlPosX->set(node.mTranslation[0]); mCtrlPosX->set(node.mTranslation[0]);
mCtrlPosY->set(node.mTranslation[1]); mCtrlPosY->set(node.mTranslation[1]);

View File

@ -42,6 +42,7 @@ namespace LL
class LLSpinCtrl; class LLSpinCtrl;
class LLMenuButton; class LLMenuButton;
class LLViewerObject;
class LLFloaterGLTFAssetEditor : public LLFloater class LLFloaterGLTFAssetEditor : public LLFloater
{ {
@ -51,6 +52,7 @@ public:
bool postBuild() override; bool postBuild() override;
void onOpen(const LLSD& key) override; void onOpen(const LLSD& key) override;
void onClose(bool app_quitting) override;
void initFolderRoot(); void initFolderRoot();
LLGLTFViewModel& getRootViewModel() { return mGLTFViewModel; } LLGLTFViewModel& getRootViewModel() { return mGLTFViewModel; }
@ -60,6 +62,8 @@ public:
void loadFromNode(S32 node, LLFolderViewFolder* parent); void loadFromNode(S32 node, LLFolderViewFolder* parent);
void loadFromSelection(); void loadFromSelection();
void dirty();
protected: protected:
void onFolderSelectionChanged(const std::deque<LLFolderViewItem*>& items, bool user_action); void onFolderSelectionChanged(const std::deque<LLFolderViewItem*>& items, bool user_action);
void onCommitTransform(); void onCommitTransform();
@ -69,8 +73,11 @@ protected:
void setTransformsEnabled(bool val); void setTransformsEnabled(bool val);
void loadNodeTransforms(S32 id); void loadNodeTransforms(S32 id);
void clearRoot();
private: private:
LLPointer<LLViewerObject> mObject;
std::shared_ptr<LL::GLTF::Asset> mAsset; std::shared_ptr<LL::GLTF::Asset> mAsset;
// Folder view related // Folder view related
@ -79,6 +86,7 @@ private:
LLPanel* mItemListPanel = nullptr; LLPanel* mItemListPanel = nullptr;
LLFolderView* mFolderRoot = nullptr; LLFolderView* mFolderRoot = nullptr;
LLScrollContainer* mScroller = nullptr; LLScrollContainer* mScroller = nullptr;
std::map<S32, LLFolderViewItem*> mNodeToItemMap;
// Transforms panel // Transforms panel
LLVector3 mLastEulerDegrees; LLVector3 mLastEulerDegrees;

View File

@ -4193,6 +4193,13 @@ U32 LLModelPreview::loadTextures(LLImportMaterial& material, void* opaque)
LLPointer< LLViewerFetchedTexture >& tex = (*reinterpret_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData)); LLPointer< LLViewerFetchedTexture >& tex = (*reinterpret_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData));
tex = LLViewerTextureManager::getFetchedTextureFromUrl("file://" + LLURI::unescape(material.mDiffuseMapFilename), FTT_LOCAL_FILE, true, LLGLTexture::BOOST_PREVIEW); tex = LLViewerTextureManager::getFetchedTextureFromUrl("file://" + LLURI::unescape(material.mDiffuseMapFilename), FTT_LOCAL_FILE, true, LLGLTexture::BOOST_PREVIEW);
if (tex->getDiscardLevel() < tex->getMaxDiscardLevel())
{
// file was loaded previosly, reload image to get potential changes
tex->clearFetchedResults();
}
// Todo: might cause a crash if preview gets closed before we get the callback.
// Use a callback list or guard callback in some way
tex->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, true, false, opaque, NULL, false); tex->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, true, false, opaque, NULL, false);
tex->forceToSaveRawImage(0, F32_MAX); tex->forceToSaveRawImage(0, F32_MAX);
material.setDiffuseMap(tex->getID()); // record tex ID material.setDiffuseMap(tex->getID()); // record tex ID

View File

@ -57,6 +57,7 @@
#include "llaudioengine.h" // <FS:PP> For object deletion sound #include "llaudioengine.h" // <FS:PP> For object deletion sound
#include "llviewerwindow.h" #include "llviewerwindow.h"
#include "lldrawable.h" #include "lldrawable.h"
#include "llfloatergltfasseteditor.h"
#include "llfloaterinspect.h" #include "llfloaterinspect.h"
#include "llfloaterproperties.h" // <FS:Ansariel> Keep legacy properties floater #include "llfloaterproperties.h" // <FS:Ansariel> Keep legacy properties floater
#include "llfloaterreporter.h" #include "llfloaterreporter.h"
@ -490,6 +491,11 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectOnly(LLViewerObject* object, S3
if (object->isSelected() ) { if (object->isSelected() ) {
// make sure point at position is updated // make sure point at position is updated
updatePointAt(); updatePointAt();
LLSelectNode* nodep = mSelectedObjects->findNode(object);
if (nodep)
{
nodep->selectGLTFNode(gltf_node, gltf_primitive, true);
}
gEditMenuHandler = this; gEditMenuHandler = this;
return NULL; return NULL;
} }
@ -7461,6 +7467,12 @@ void dialog_refresh_all()
{ {
panel_task_info->dirty(); panel_task_info->dirty();
} }
LLFloaterGLTFAssetEditor * gltf_editor = LLFloaterReg::getTypedInstance<LLFloaterGLTFAssetEditor>("gltf_asset_editor");
if (gltf_editor)
{
gltf_editor->dirty();
}
} }
S32 get_family_count(LLViewerObject *parent) S32 get_family_count(LLViewerObject *parent)

View File

@ -554,6 +554,9 @@ void LLGLTexMemBar::draw()
F64 raw_image_bytes_MB = raw_image_bytes / (1024.0 * 1024.0); 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 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 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; LLGLSUIDefault gls_ui;
@ -583,7 +586,7 @@ void LLGLTexMemBar::draw()
// draw a background above first line.... no idea where the rest of the background comes from for the below text // 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); 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 GL Tex: %d MB FBO: %d MB Bias: %.2f Cache: %.1f/%.1f MB", text = llformat("Est. Free: %d MB Sys Free: %d MB GL Tex: %d MB FBO: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
(S32)LLViewerTexture::sFreeVRAMMegabytes, (S32)LLViewerTexture::sFreeVRAMMegabytes,
@ -594,8 +597,8 @@ void LLGLTexMemBar::draw()
cache_usage, cache_usage,
cache_max_usage); cache_max_usage);
// <FS:Ansariel> Texture memory bars // <FS:Ansariel> Texture memory bars
//LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*6, //LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*7,
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*8, LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*9,
// </FS:Ansariel> // </FS:Ansariel>
text_color, LLFontGL::LEFT, LLFontGL::TOP); text_color, LLFontGL::LEFT, LLFontGL::TOP);
@ -603,7 +606,7 @@ void LLGLTexMemBar::draw()
S32 bar_left = 0; S32 bar_left = 0;
constexpr S32 bar_width = 200; constexpr S32 bar_width = 200;
constexpr S32 bar_space = 10; constexpr S32 bar_space = 10;
S32 top = line_height*7 - 2 + v_offset; S32 top = line_height*8 - 2 + v_offset;
S32 bottom = top - 6; S32 bottom = top - 6;
S32 left = bar_left; S32 left = bar_left;
S32 right = left + bar_width; S32 right = left + bar_width;
@ -613,7 +616,7 @@ void LLGLTexMemBar::draw()
// VRAM Mem Bar // VRAM Mem Bar
text = "VRAM"; text = "VRAM";
LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, v_offset + line_height*7, LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, v_offset + line_height*8,
text_color, LLFontGL::LEFT, LLFontGL::TOP); text_color, LLFontGL::LEFT, LLFontGL::TOP);
left += 35; left += 35;
right = left + bar_width; right = left + bar_width;
@ -636,7 +639,7 @@ void LLGLTexMemBar::draw()
left = bar_left; left = bar_left;
// VRAM Mem Bar // VRAM Mem Bar
text = "CACHE"; text = "CACHE";
LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, v_offset + line_height*7, LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, v_offset + line_height*8,
text_color, LLFontGL::LEFT, LLFontGL::TOP); text_color, LLFontGL::LEFT, LLFontGL::TOP);
left += 35; left += 35;
@ -658,6 +661,14 @@ void LLGLTexMemBar::draw()
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, 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, saved_raw_image_count, saved_raw_image_bytes_MB,
aux_raw_image_count, aux_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, LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height * 6,
text_color, LLFontGL::LEFT, LLFontGL::TOP); text_color, LLFontGL::LEFT, LLFontGL::TOP);

View File

@ -379,6 +379,7 @@ void LLViewerAssetStorage::queueRequestHttp(
bool duplicate, bool duplicate,
bool is_priority) bool is_priority)
{ {
LL_PROFILE_ZONE_SCOPED;
LL_DEBUGS("ViewerAsset") << "Request asset via HTTP " << uuid << " type " << LLAssetType::lookup(atype) << LL_ENDL; LL_DEBUGS("ViewerAsset") << "Request asset via HTTP " << uuid << " type " << LLAssetType::lookup(atype) << LL_ENDL;
bool with_http = true; bool with_http = true;

View File

@ -4581,6 +4581,7 @@ void LLViewerObject::moveGLTFNode(S32 node_index, const LLVector3& offset)
matMul(trans, mat, mat); matMul(trans, mat, mat);
node.mMatrix = glm::make_mat4(mat.getF32ptr()); node.mMatrix = glm::make_mat4(mat.getF32ptr());
node.mTRSValid = false;
// TODO -- only update transforms for this node and its children (or use a dirty flag) // TODO -- only update transforms for this node and its children (or use a dirty flag)
mGLTFAsset->updateTransforms(); mGLTFAsset->updateTransforms();

View File

@ -97,7 +97,7 @@ S32 LLViewerTexture::sRawCount = 0;
S32 LLViewerTexture::sAuxCount = 0; S32 LLViewerTexture::sAuxCount = 0;
LLFrameTimer LLViewerTexture::sEvaluationTimer; LLFrameTimer LLViewerTexture::sEvaluationTimer;
F32 LLViewerTexture::sDesiredDiscardBias = 0.f; F32 LLViewerTexture::sDesiredDiscardBias = 0.f;
F32 LLViewerTexture::sDesiredDiscardScale = 1.1f;
S32 LLViewerTexture::sMaxSculptRez = 128; //max sculpt image size S32 LLViewerTexture::sMaxSculptRez = 128; //max sculpt image size
const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64; const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64;
const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez; const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez;
@ -532,15 +532,18 @@ void LLViewerTexture::updateClass()
F32 target = llmax(budget - 512.f, MIN_VRAM_BUDGET); F32 target = llmax(budget - 512.f, MIN_VRAM_BUDGET);
sFreeVRAMMegabytes = target - used; 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()) if (isSystemMemoryLow())
{ {
is_low = true;
// System RAM is low -> ramp up discard bias over time to free memory // System RAM is low -> ramp up discard bias over time to free memory
if (sEvaluationTimer.getElapsedTimeF32() > MEMORY_CHECK_WAIT_TIME) if (sEvaluationTimer.getElapsedTimeF32() > MEMORY_CHECK_WAIT_TIME)
{ {
static LLCachedControl<F32> low_mem_min_discard_increment(gSavedSettings, "RenderLowMemMinDiscardIncrement", .1f); 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(); sEvaluationTimer.reset();
} }
} }
@ -548,12 +551,28 @@ void LLViewerTexture::updateClass()
{ {
sDesiredDiscardBias = llmax(sDesiredDiscardBias, 1.f + over_pct); sDesiredDiscardBias = llmax(sDesiredDiscardBias, 1.f + over_pct);
if (sDesiredDiscardBias > 1.f) if (sDesiredDiscardBias > 1.f && over_pct < 0.f)
{ {
sDesiredDiscardBias -= gFrameIntervalSeconds * 0.01; 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; LLViewerTexture::sFreezeImageUpdates = false;
} }
@ -634,16 +653,15 @@ void LLViewerTexture::init(bool firstinit)
mParcelMedia = NULL; mParcelMedia = NULL;
memset(&mNumVolumes, 0, sizeof(U32)* LLRender::NUM_VOLUME_TEXTURE_CHANNELS); 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::LIGHT_TEX].clear();
mVolumeList[LLRender::SCULPT_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"); mMainQueue = LL::WorkQueue::getInstance("mainloop");
mImageQueue = LL::WorkQueue::getInstance("LLImageGL"); mImageQueue = LL::WorkQueue::getInstance("LLImageGL");
} }
@ -1674,7 +1692,11 @@ void LLViewerFetchedTexture::scheduleCreateTexture()
} }
else else
{ {
gTextureList.mCreateTextureList.insert(this); if (!mCreatePending)
{
mCreatePending = true;
gTextureList.mCreateTextureList.push(this);
}
} }
} }
} }
@ -1698,13 +1720,12 @@ void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height)
void LLViewerFetchedTexture::setDebugText(const std::string& text) 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 (S32 fi = 0; fi < getNumFaces(i); ++fi)
{
LLFace* facep = (*(getFaceList(i)))[fi];
for (U32 i = 0; i < mNumFaces[ch]; i++)
{
LLFace* facep = mFaceList[ch][i];
if (facep) if (facep)
{ {
LLDrawable* drawable = facep->getDrawable(); LLDrawable* drawable = facep->getDrawable();
@ -1717,10 +1738,15 @@ void LLViewerFetchedTexture::setDebugText(const std::string& text)
} }
} }
extern bool gCubeSnapshot;
//virtual //virtual
void LLViewerFetchedTexture::processTextureStats() void LLViewerFetchedTexture::processTextureStats()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
llassert(!gCubeSnapshot); // should only be called when the main camera is active
llassert(!LLPipeline::sShadowRender);
if(mFullyLoaded) if(mFullyLoaded)
{ {
if(mDesiredDiscardLevel > mMinDesiredDiscardLevel)//need to load more if(mDesiredDiscardLevel > mMinDesiredDiscardLevel)//need to load more
@ -2941,6 +2967,8 @@ void LLViewerLODTexture::processTextureStats()
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
updateVirtualSize(); updateVirtualSize();
bool did_downscale = false;
static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes", false); static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes", false);
{ // restrict texture resolution to download based on RenderMaxTextureResolution { // restrict texture resolution to download based on RenderMaxTextureResolution
@ -2998,10 +3026,7 @@ void LLViewerLODTexture::processTextureStats()
mDiscardVirtualSize = mMaxVirtualSize; mDiscardVirtualSize = mMaxVirtualSize;
mCalculatedDiscardLevel = discard_level; mCalculatedDiscardLevel = discard_level;
} }
if (mBoostLevel < LLGLTexture::BOOST_SCULPTED)
{
discard_level *= sDesiredDiscardScale; // scale (default 1.1f)
}
discard_level = floorf(discard_level); discard_level = floorf(discard_level);
F32 min_discard = 0.f; F32 min_discard = 0.f;
@ -3027,10 +3052,9 @@ void LLViewerLODTexture::processTextureStats()
// //
S32 current_discard = getDiscardLevel(); S32 current_discard = getDiscardLevel();
if (mBoostLevel < LLGLTexture::BOOST_AVATAR_BAKED && if (mBoostLevel < LLGLTexture::BOOST_AVATAR_BAKED)
current_discard >= 0)
{ {
if (current_discard < (mDesiredDiscardLevel-1) && !mForceToSaveRawImage) if (current_discard < mDesiredDiscardLevel && !mForceToSaveRawImage)
{ // should scale down { // should scale down
scaleDown(); scaleDown();
} }
@ -3050,9 +3074,6 @@ void LLViewerLODTexture::processTextureStats()
mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel); 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 // selection manager will immediately reset BOOST_SELECTED but never unsets it
// unset it immediately after we consume it // unset it immediately after we consume it
if (getBoostLevel() == BOOST_SELECTED) if (getBoostLevel() == BOOST_SELECTED)
@ -3061,14 +3082,22 @@ void LLViewerLODTexture::processTextureStats()
} }
} }
extern LLGLSLShader gCopyProgram;
bool LLViewerLODTexture::scaleDown() bool LLViewerLODTexture::scaleDown()
{ {
if (mGLTexturep.isNull()) if (mGLTexturep.isNull() || !mGLTexturep->getHasGLTexture())
{ {
return false; return false;
} }
return mGLTexturep->scaleDown(mDesiredDiscardLevel); if (!mDownScalePending)
{
mDownScalePending = true;
gTextureList.mDownScaleQueue.push(this);
}
return true;
} }
//---------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------

View File

@ -37,6 +37,7 @@
#include "llmetricperformancetester.h" #include "llmetricperformancetester.h"
#include "httpcommon.h" #include "httpcommon.h"
#include "workqueue.h" #include "workqueue.h"
#include "gltf/common.h"
#include <map> #include <map>
#include <list> #include <list>
@ -108,7 +109,6 @@ public:
DYNAMIC_TEXTURE, DYNAMIC_TEXTURE,
FETCHED_TEXTURE, FETCHED_TEXTURE,
LOD_TEXTURE, LOD_TEXTURE,
ATLAS_TEXTURE,
INVALID_TEXTURE_TYPE INVALID_TEXTURE_TYPE
}; };
@ -181,6 +181,15 @@ public:
LLViewerMediaTexture* getParcelMedia() const { return mParcelMedia;} LLViewerMediaTexture* getParcelMedia() const { return mParcelMedia;}
/*virtual*/ void updateBindStatsForTester() ; /*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: protected:
void cleanup() ; void cleanup() ;
void init(bool firstinit) ; void init(bool firstinit) ;
@ -222,7 +231,6 @@ public:
static S32 sAuxCount; static S32 sAuxCount;
static LLFrameTimer sEvaluationTimer; static LLFrameTimer sEvaluationTimer;
static F32 sDesiredDiscardBias; static F32 sDesiredDiscardBias;
static F32 sDesiredDiscardScale;
static S32 sMaxSculptRez ; static S32 sMaxSculptRez ;
static U32 sMinLargeImageSize ; static U32 sMinLargeImageSize ;
static U32 sMaxSmallImageSize ; static U32 sMaxSmallImageSize ;
@ -445,6 +453,9 @@ public:
/*virtual*/bool isActiveFetching() override; //is actively in fetching by the fetching pipeline. /*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
// <FS:Techwolf Lupindo> texture comment decoder // <FS:Techwolf Lupindo> texture comment decoder
std::map<std::string,std::string> mComment; std::map<std::string,std::string> mComment;
// </FS:Techwolf Lupindo> // </FS:Techwolf Lupindo>
@ -460,11 +471,6 @@ private:
void saveRawImage() ; void saveRawImage() ;
//for atlas
void resetFaceAtlas() ;
void invalidateAtlas(bool rebuild_geom) ;
bool insertToAtlas() ;
private: private:
bool mFullyLoaded; bool mFullyLoaded;
bool mInDebug; bool mInDebug;
@ -579,9 +585,10 @@ public:
/*virtual*/ void processTextureStats(); /*virtual*/ void processTextureStats();
bool isUpdateFrozen() ; bool isUpdateFrozen() ;
bool scaleDown();
private: private:
void init(bool firstinit) ; void init(bool firstinit) ;
bool scaleDown() ;
private: private:
F32 mDiscardVirtualSize; // Virtual size used to calculate desired discard F32 mDiscardVirtualSize; // Virtual size used to calculate desired discard

View File

@ -73,6 +73,8 @@ U32 LLViewerTextureList::sNumFastCacheReads = 0;
LLViewerTextureList gTextureList; LLViewerTextureList gTextureList;
extern LLGLSLShader gCopyProgram;
ETexListType get_element_type(S32 priority) ETexListType get_element_type(S32 priority)
{ {
return (priority == LLViewerFetchedTexture::BOOST_ICON || priority == LLViewerFetchedTexture::BOOST_THUMBNAIL) ? TEX_LIST_SCALE : TEX_LIST_STANDARD; return (priority == LLViewerFetchedTexture::BOOST_ICON || priority == LLViewerFetchedTexture::BOOST_THUMBNAIL) ? TEX_LIST_SCALE : TEX_LIST_STANDARD;
@ -360,8 +362,11 @@ void LLViewerTextureList::shutdown()
mCallbackList.clear(); mCallbackList.clear();
// Flush all of the references // Flush all of the references
mLoadingStreamList.clear(); while (!mCreateTextureList.empty())
mCreateTextureList.clear(); {
mCreateTextureList.front()->mCreatePending = false;
mCreateTextureList.pop();
}
mFastCacheList.clear(); mFastCacheList.clear();
mUUIDMap.clear(); mUUIDMap.clear();
@ -910,14 +915,6 @@ void LLViewerTextureList::clearFetchingRequests()
} }
} }
static void touch_texture(LLViewerFetchedTexture* tex, F32 vsize)
{
if (tex)
{
tex->addTextureStats(vsize);
}
}
extern bool gCubeSnapshot; extern bool gCubeSnapshot;
void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imagep) void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imagep)
@ -934,15 +931,21 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag
static LLCachedControl<F32> texture_scale_min(gSavedSettings, "TextureScaleMinAreaFactor", 0.04f); static LLCachedControl<F32> texture_scale_min(gSavedSettings, "TextureScaleMinAreaFactor", 0.04f);
static LLCachedControl<F32> texture_scale_max(gSavedSettings, "TextureScaleMaxAreaFactor", 25.f); 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 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]; LLFace* face = (*(imagep->getFaceList(i)))[fi];
if (face && face->getViewerObject() && face->getTextureEntry()) if (face && face->getViewerObject())
{ {
F32 radius; F32 radius;
F32 cos_angle_to_view_dir; F32 cos_angle_to_view_dir;
@ -958,32 +961,35 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag
// Maximum usage examples: huge chunk of terrain repeats texture // Maximum usage examples: huge chunk of terrain repeats texture
const LLTextureEntry* te = face->getTextureEntry(); const LLTextureEntry* te = face->getTextureEntry();
F32 min_scale = te ? llmin(fabsf(te->getScaleS()), fabsf(te->getScaleT())) : 1.f; 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()); min_scale = llclamp(min_scale * min_scale, texture_scale_min(), texture_scale_max());
vsize /= min_scale; vsize /= min_scale;
// if bias is > 2, apply to on-screen textures as well
bool apply_bias = LLViewerTexture::sDesiredDiscardBias > 2.f;
// 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) if (!in_frustum || !face->getDrawable()->isVisible() || face->getImportanceToCamera() < bias_unimportant_threshold)
{ // further reduce by discard bias when off screen or occluded { // further reduce by discard bias when off screen or occluded
vsize /= LLViewerTexture::sDesiredDiscardBias; apply_bias = true;
} }
// if a GLTF material is present, ignore that face
// as far as this texture stats go, but update the GLTF material if (apply_bias)
// stats
LLFetchedGLTFMaterial* mat = te ? (LLFetchedGLTFMaterial*)te->getGLTFRenderMaterial() : nullptr;
llassert(mat == nullptr || dynamic_cast<LLFetchedGLTFMaterial*>(te->getGLTFRenderMaterial()) != nullptr);
if (mat)
{ {
touch_texture(mat->mBaseColorTexture, vsize); F32 bias = powf(4, LLViewerTexture::sDesiredDiscardBias - 1.f);
touch_texture(mat->mNormalTexture, vsize); bias = llround(bias);
touch_texture(mat->mMetallicRoughnessTexture, vsize); vsize /= bias;
touch_texture(mat->mEmissiveTexture, vsize);
} }
else
{
imagep->addTextureStats(vsize); 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())); //imagep->setDebugText(llformat("%.3f - %d", sqrtf(imagep->getMaxVirtualSize()), imagep->getBoostLevel()));
@ -1079,22 +1085,65 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time)
// //
LLTimer create_timer; LLTimer create_timer;
image_list_t::iterator enditer = mCreateTextureList.begin();
for (image_list_t::iterator iter = mCreateTextureList.begin();
iter != mCreateTextureList.end();)
{
image_list_t::iterator curiter = iter++;
enditer = iter;
LLViewerFetchedTexture *imagep = *curiter;
imagep->createTexture();
imagep->postCreateTexture();
if (create_timer.getElapsedTimeF32() > max_time) if (!mDownScaleQueue.empty() && gPipeline.mDownResMap.isComplete())
{
// 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 && --min_count <= 0)
{ {
break; break;
} }
} }
mCreateTextureList.erase(mCreateTextureList.begin(), enditer);
return create_timer.getElapsedTimeF32(); return create_timer.getElapsedTimeF32();
} }
@ -1140,7 +1189,10 @@ void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep)
removeImageFromList(imagep); removeImageFromList(imagep);
} }
if (!gCubeSnapshot)
{ // never call processTextureStats in a cube snapshot
imagep->processTextureStats(); imagep->processTextureStats();
}
imagep->sMaxVirtualSize = LLViewerFetchedTexture::sMaxVirtualSize; imagep->sMaxVirtualSize = LLViewerFetchedTexture::sMaxVirtualSize;
addImageToList(imagep); addImageToList(imagep);
@ -1150,6 +1202,7 @@ void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep)
F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
typedef std::vector<LLPointer<LLViewerFetchedTexture> > entries_list_t; typedef std::vector<LLPointer<LLViewerFetchedTexture> > entries_list_t;
entries_list_t entries; entries_list_t entries;

View File

@ -148,12 +148,13 @@ public:
void clearFetchingRequests(); void clearFetchingRequests();
void setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level); void setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level);
private:
// do some book keeping on the specified texture // do some book keeping on the specified texture
// - updates decode priority // - updates decode priority
// - updates desired discard level // - updates desired discard level
// - cleans up textures that haven't been referenced in awhile // - cleans up textures that haven't been referenced in awhile
void updateImageDecodePriority(LLViewerFetchedTexture* imagep); void updateImageDecodePriority(LLViewerFetchedTexture* imagep);
private:
F32 updateImagesCreateTextures(F32 max_time); F32 updateImagesCreateTextures(F32 max_time);
F32 updateImagesFetchTextures(F32 max_time); F32 updateImagesFetchTextures(F32 max_time);
void updateImagesUpdateStats(); void updateImagesUpdateStats();
@ -217,8 +218,14 @@ private: // PoundLife - Improved Object Inspect
public: public:
typedef std::unordered_set<LLPointer<LLViewerFetchedTexture> > image_list_t; typedef std::unordered_set<LLPointer<LLViewerFetchedTexture> > image_list_t;
image_list_t mLoadingStreamList; typedef std::queue<LLPointer<LLViewerFetchedTexture> > image_queue_t;
image_list_t mCreateTextureList;
// 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 mCallbackList;
image_list_t mFastCacheList; image_list_t mFastCacheList;

View File

@ -461,6 +461,9 @@ void LLVOGrass::plantBlades()
face->setVertexBuffer(NULL); face->setVertexBuffer(NULL);
face->setTEOffset(0); face->setTEOffset(0);
face->mCenterLocal = mPosition + mRegionp->getOriginAgent(); 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(); mDepth = (face->mCenterLocal - LLViewerCamera::getInstance()->getOrigin())*LLViewerCamera::getInstance()->getAtAxis();

View File

@ -472,9 +472,7 @@ void LLVOTree::updateTextures()
{ {
setDebugText(llformat("%4.0f", (F32) sqrt(mPixelArea))); setDebugText(llformat("%4.0f", (F32) sqrt(mPixelArea)));
} }
mTreeImagep->addTextureStats(mPixelArea);
} }
} }
@ -490,7 +488,7 @@ LLDrawable* LLVOTree::createDrawable(LLPipeline *pipeline)
// Just a placeholder for an actual object... // Just a placeholder for an actual object...
LLFace *facep = mDrawable->addFace(poolp, mTreeImagep); LLFace *facep = mDrawable->addFace(poolp, mTreeImagep);
facep->setSize(1, 3); facep->setSize(1, 3);
facep->setTexture(LLRender::DIFFUSE_MAP, mTreeImagep);
updateRadius(); updateRadius();
return mDrawable; return mDrawable;
@ -1180,6 +1178,10 @@ void LLVOTree::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
LLVector4a pos; LLVector4a pos;
pos.load3(center.mV); pos.load3(center.mV);
mDrawable->setPositionGroup(pos); 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, bool LLVOTree::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, bool pick_transparent, bool pick_rigged, bool pick_unselectable, S32 *face_hitp,

View File

@ -6072,18 +6072,23 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
{ {
continue; continue;
} }
#if 0
#if LL_RELEASE_WITH_DEBUG_INFO LLFetchedGLTFMaterial *gltf_mat = (LLFetchedGLTFMaterial*) facep->getTextureEntry()->getGLTFRenderMaterial();
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();
bool is_pbr = gltf_mat != nullptr; 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 //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 // batch, it will recover its vertex buffer reference from the spatial group

View File

@ -961,6 +961,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
const U32 post_color_fmt = post_hdr ? GL_RGBA16F : GL_RGBA; const U32 post_color_fmt = post_hdr ? GL_RGBA16F : GL_RGBA;
mPostMap.allocate(resX, resY, post_color_fmt); 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 //HACK make screenbuffer allocations start failing after 30 seconds
if (gSavedSettings.getBOOL("SimulateFBOFailure")) if (gSavedSettings.getBOOL("SimulateFBOFailure"))
{ {
@ -1221,6 +1225,8 @@ void LLPipeline::releaseGLBuffers()
mPostMap.release(); mPostMap.release();
mDownResMap.release();
for (U32 i = 0; i < 3; i++) for (U32 i = 0; i < 3; i++)
{ {
mGlow[i].release(); mGlow[i].release();

View File

@ -741,6 +741,9 @@ public:
// tonemapped and gamma corrected render ready for post // tonemapped and gamma corrected render ready for post
LLRenderTarget mPostMap; LLRenderTarget mPostMap;
// downres scratch space for GPU downscaling of textures
LLRenderTarget mDownResMap;
LLCullResult mSky; LLCullResult mSky;
LLCullResult mReflectedObjects; LLCullResult mReflectedObjects;
LLCullResult mRefractedObjects; LLCullResult mRefractedObjects;