diff options
70 files changed, 1705 insertions, 1699 deletions
diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index d2c4e66160..6e988260a9 100644 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -37,12 +37,13 @@ thread_local bool gProfilerEnabled = false; #if (TRACY_ENABLE) // Override new/delete for tracy memory profiling -void *operator new(size_t size) + +void* ll_tracy_new(size_t size) { void* ptr; if (gProfilerEnabled) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY; + //LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY; ptr = (malloc)(size); } else @@ -57,12 +58,22 @@ void *operator new(size_t size) return ptr; } -void operator delete(void *ptr) noexcept +void* operator new(size_t size) +{ + return ll_tracy_new(size); +} + +void* operator new[](std::size_t count) +{ + return ll_tracy_new(count); +} + +void ll_tracy_delete(void* ptr) { TracyFree(ptr); if (gProfilerEnabled) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY; + //LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY; (free)(ptr); } else @@ -71,6 +82,16 @@ void operator delete(void *ptr) noexcept } } +void operator delete(void *ptr) noexcept +{ + ll_tracy_delete(ptr); +} + +void operator delete[](void* ptr) noexcept +{ + ll_tracy_delete(ptr); +} + // C-style malloc/free can't be so easily overridden, so we define tracy versions and use // a pre-processor #define in linden_common.h to redirect to them. The parens around the native // functions below prevents recursive substitution by the preprocessor. diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index d06c0e2132..b7dec3cb7f 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -82,9 +82,11 @@ const int LL_ERR_NOERR = 0; #ifdef SHOW_ASSERT #define llassert(func) llassert_always_msg(func, #func) +#define llassert_msg(func, msg) llassert_always_msg(func, msg) #define llverify(func) llassert_always_msg(func, #func) #else #define llassert(func) +#define llassert_msg(func, msg) #define llverify(func) do {if (func) {}} while(0) #endif diff --git a/indra/llcommon/llprofiler.h b/indra/llcommon/llprofiler.h index 394fbd05f6..736a069f49 100644 --- a/indra/llcommon/llprofiler.h +++ b/indra/llcommon/llprofiler.h @@ -138,10 +138,6 @@ extern thread_local bool gProfilerEnabled; #define LL_PROFILE_ZONE_ERR(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0XFF0000 ) // RGB yellow #define LL_PROFILE_ZONE_INFO(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0X00FFFF ) // RGB cyan #define LL_PROFILE_ZONE_WARN(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0x0FFFF00 ) // RGB red - //#define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size) // memory allocation tracking currently not working - //#define LL_PROFILE_FREE(ptr) TracyFree(ptr) - #define LL_PROFILE_ALLOC(ptr, size) (void)(ptr); (void)(size); - #define LL_PROFILE_FREE(ptr) (void)(ptr); #endif #else #define LL_PROFILER_FRAME_END @@ -165,7 +161,7 @@ extern thread_local bool gProfilerEnabled; #define LL_LABEL_OBJECT_GL(type, name, length, label) -#if LL_PROFILER_CONFIG > 1 +#if LL_PROFILER_CONFIGURATION > 1 #define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size) #define LL_PROFILE_FREE(ptr) TracyFree(ptr) #else diff --git a/indra/llcommon/llprofilercategories.h b/indra/llcommon/llprofilercategories.h index 8db29468cc..617431f629 100644 --- a/indra/llcommon/llprofilercategories.h +++ b/indra/llcommon/llprofilercategories.h @@ -52,7 +52,7 @@ #define LL_PROFILER_CATEGORY_ENABLE_LOGGING 1 #define LL_PROFILER_CATEGORY_ENABLE_MATERIAL 1 #define LL_PROFILER_CATEGORY_ENABLE_MEDIA 1 -#define LL_PROFILER_CATEGORY_ENABLE_MEMORY 1 +#define LL_PROFILER_CATEGORY_ENABLE_MEMORY 0 #define LL_PROFILER_CATEGORY_ENABLE_NETWORK 1 #define LL_PROFILER_CATEGORY_ENABLE_OCTREE 1 #define LL_PROFILER_CATEGORY_ENABLE_PIPELINE 1 diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index fc04dca08d..3619a64ea9 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -1,31 +1,31 @@ -/** +/** * @file lluuid.cpp * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "linden_common.h" -// We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes. + // We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes. #if LL_WINDOWS #include "llwin32headers.h" // ugh, this is ugly. We need to straighten out our linking for this library @@ -40,18 +40,17 @@ #include "lluuid.h" #include "llerror.h" #include "llrand.h" +#include "llmd5.h" #include "llstring.h" #include "lltimer.h" #include "llthread.h" #include "llmutex.h" -#include "llmd5.h" -#include "hbxxh.h" const LLUUID LLUUID::null; const LLTransactionID LLTransactionID::tnull; // static -LLMutex * LLUUID::mMutex = NULL; +LLMutex* LLUUID::mMutex = NULL; @@ -60,15 +59,15 @@ LLMutex * LLUUID::mMutex = NULL; NOT DONE YET!!! static char BASE85_TABLE[] = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', - 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '!', '#', '$', '%', '&', '(', ')', '*', - '+', '-', ';', '[', '=', '>', '?', '@', '^', '_', - '`', '{', '|', '}', '~', '\0' + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '!', '#', '$', '%', '&', '(', ')', '*', + '+', '-', ';', '[', '=', '>', '?', '@', '^', '_', + '`', '{', '|', '}', '~', '\0' }; @@ -94,28 +93,28 @@ return ret; void LLUUID::toBase85(char* out) { - U32* me = (U32*)&(mData[0]); - for(S32 i = 0; i < 4; ++i) - { - char* o = &out[i*i]; - for(S32 j = 0; j < 5; ++j) - { - o[4-j] = BASE85_TABLE[ me[i] % 85]; - word /= 85; - } - } + U32* me = (U32*)&(mData[0]); + for(S32 i = 0; i < 4; ++i) + { + char* o = &out[i*i]; + for(S32 j = 0; j < 5; ++j) + { + o[4-j] = BASE85_TABLE[ me[i] % 85]; + word /= 85; + } + } } unsigned int decode( char const * fiveChars ) throw( bad_input_data ) { - unsigned int ret = 0; - for( S32 ix = 0; ix < 5; ++ix ) - { - char * s = strchr( encodeTable, fiveChars[ ix ] ); - ret = ret * 85 + (s-encodeTable); - } - return ret; -} + unsigned int ret = 0; + for( S32 ix = 0; ix < 5; ++ix ) + { + char * s = strchr( encodeTable, fiveChars[ ix ] ); + ret = ret * 85 + (s-encodeTable); + } + return ret; +} */ #define LL_USE_JANKY_RANDOM_NUMBER_GENERATOR 0 @@ -130,8 +129,8 @@ static U64 sJankyRandomSeed(LLUUID::getRandomSeed()); */ U32 janky_fast_random_bytes() { - sJankyRandomSeed = U64L(1664525) * sJankyRandomSeed + U64L(1013904223); - return (U32)sJankyRandomSeed; + sJankyRandomSeed = U64L(1664525) * sJankyRandomSeed + U64L(1013904223); + return (U32)sJankyRandomSeed; } /** @@ -139,8 +138,8 @@ U32 janky_fast_random_bytes() */ U32 janky_fast_random_byes_range(U32 val) { - sJankyRandomSeed = U64L(1664525) * sJankyRandomSeed + U64L(1013904223); - return (U32)(sJankyRandomSeed) % val; + sJankyRandomSeed = U64L(1664525) * sJankyRandomSeed + U64L(1013904223); + return (U32)(sJankyRandomSeed) % val; } /** @@ -148,365 +147,362 @@ U32 janky_fast_random_byes_range(U32 val) */ U32 janky_fast_random_seeded_bytes(U32 seed, U32 val) { - seed = U64L(1664525) * (U64)(seed) + U64L(1013904223); - return (U32)(seed) % val; + seed = U64L(1664525) * (U64)(seed)+U64L(1013904223); + return (U32)(seed) % val; } #endif // Common to all UUID implementations void LLUUID::toString(std::string& out) const { - out = llformat( - "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - (U8)(mData[0]), - (U8)(mData[1]), - (U8)(mData[2]), - (U8)(mData[3]), - (U8)(mData[4]), - (U8)(mData[5]), - (U8)(mData[6]), - (U8)(mData[7]), - (U8)(mData[8]), - (U8)(mData[9]), - (U8)(mData[10]), - (U8)(mData[11]), - (U8)(mData[12]), - (U8)(mData[13]), - (U8)(mData[14]), - (U8)(mData[15])); + out = llformat( + "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + (U8)(mData[0]), + (U8)(mData[1]), + (U8)(mData[2]), + (U8)(mData[3]), + (U8)(mData[4]), + (U8)(mData[5]), + (U8)(mData[6]), + (U8)(mData[7]), + (U8)(mData[8]), + (U8)(mData[9]), + (U8)(mData[10]), + (U8)(mData[11]), + (U8)(mData[12]), + (U8)(mData[13]), + (U8)(mData[14]), + (U8)(mData[15])); } // *TODO: deprecate -void LLUUID::toString(char *out) const +void LLUUID::toString(char* out) const { - std::string buffer; - toString(buffer); - strcpy(out,buffer.c_str()); /* Flawfinder: ignore */ + std::string buffer; + toString(buffer); + strcpy(out, buffer.c_str()); /* Flawfinder: ignore */ } void LLUUID::toCompressedString(std::string& out) const { - char bytes[UUID_BYTES+1]; - memcpy(bytes, mData, UUID_BYTES); /* Flawfinder: ignore */ - bytes[UUID_BYTES] = '\0'; - out.assign(bytes, UUID_BYTES); + char bytes[UUID_BYTES + 1]; + memcpy(bytes, mData, UUID_BYTES); /* Flawfinder: ignore */ + bytes[UUID_BYTES] = '\0'; + out.assign(bytes, UUID_BYTES); } // *TODO: deprecate -void LLUUID::toCompressedString(char *out) const +void LLUUID::toCompressedString(char* out) const { - memcpy(out, mData, UUID_BYTES); /* Flawfinder: ignore */ - out[UUID_BYTES] = '\0'; + memcpy(out, mData, UUID_BYTES); /* Flawfinder: ignore */ + out[UUID_BYTES] = '\0'; } std::string LLUUID::getString() const { - return asString(); + return asString(); } std::string LLUUID::asString() const { - std::string str; - toString(str); - return str; + std::string str; + toString(str); + return str; } BOOL LLUUID::set(const char* in_string, BOOL emit) { - return set(ll_safe_string(in_string),emit); + return set(ll_safe_string(in_string), emit); } BOOL LLUUID::set(const std::string& in_string, BOOL emit) { - BOOL broken_format = FALSE; - - // empty strings should make NULL uuid - if (in_string.empty()) - { - setNull(); - return TRUE; - } - - if (in_string.length() != (UUID_STR_LENGTH - 1)) /* Flawfinder: ignore */ - { - // I'm a moron. First implementation didn't have the right UUID format. - // Shouldn't see any of these any more - if (in_string.length() == (UUID_STR_LENGTH - 2)) /* Flawfinder: ignore */ - { - if(emit) - { - LL_WARNS() << "Warning! Using broken UUID string format" << LL_ENDL; - } - broken_format = TRUE; - } - else - { - // Bad UUID string. Spam as INFO, as most cases we don't care. - if(emit) - { - //don't spam the logs because a resident can't spell. - LL_WARNS() << "Bad UUID string: " << in_string << LL_ENDL; - } - setNull(); - return FALSE; - } - } - - U8 cur_pos = 0; - S32 i; - for (i = 0; i < UUID_BYTES; i++) - { - if ((i == 4) || (i == 6) || (i == 8) || (i == 10)) - { - cur_pos++; - if (broken_format && (i==10)) - { - // Missing - in the broken format - cur_pos--; - } - } - - mData[i] = 0; - - if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9')) - { - mData[i] += (U8)(in_string[cur_pos] - '0'); - } - else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <='f')) - { - mData[i] += (U8)(10 + in_string[cur_pos] - 'a'); - } - else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <='F')) - { - mData[i] += (U8)(10 + in_string[cur_pos] - 'A'); - } - else - { - if(emit) - { - LL_WARNS() << "Invalid UUID string character" << LL_ENDL; - } - setNull(); - return FALSE; - } - - mData[i] = mData[i] << 4; - cur_pos++; - - if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9')) - { - mData[i] += (U8)(in_string[cur_pos] - '0'); - } - else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <='f')) - { - mData[i] += (U8)(10 + in_string[cur_pos] - 'a'); - } - else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <='F')) - { - mData[i] += (U8)(10 + in_string[cur_pos] - 'A'); - } - else - { - if(emit) - { - LL_WARNS() << "Invalid UUID string character" << LL_ENDL; - } - setNull(); - return FALSE; - } - cur_pos++; - } - - return TRUE; + BOOL broken_format = FALSE; + + // empty strings should make NULL uuid + if (in_string.empty()) + { + setNull(); + return TRUE; + } + + if (in_string.length() != (UUID_STR_LENGTH - 1)) /* Flawfinder: ignore */ + { + // I'm a moron. First implementation didn't have the right UUID format. + // Shouldn't see any of these any more + if (in_string.length() == (UUID_STR_LENGTH - 2)) /* Flawfinder: ignore */ + { + if (emit) + { + LL_WARNS() << "Warning! Using broken UUID string format" << LL_ENDL; + } + broken_format = TRUE; + } + else + { + // Bad UUID string. Spam as INFO, as most cases we don't care. + if (emit) + { + //don't spam the logs because a resident can't spell. + LL_WARNS() << "Bad UUID string: " << in_string << LL_ENDL; + } + setNull(); + return FALSE; + } + } + + U8 cur_pos = 0; + S32 i; + for (i = 0; i < UUID_BYTES; i++) + { + if ((i == 4) || (i == 6) || (i == 8) || (i == 10)) + { + cur_pos++; + if (broken_format && (i == 10)) + { + // Missing - in the broken format + cur_pos--; + } + } + + mData[i] = 0; + + if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9')) + { + mData[i] += (U8)(in_string[cur_pos] - '0'); + } + else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <= 'f')) + { + mData[i] += (U8)(10 + in_string[cur_pos] - 'a'); + } + else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <= 'F')) + { + mData[i] += (U8)(10 + in_string[cur_pos] - 'A'); + } + else + { + if (emit) + { + LL_WARNS() << "Invalid UUID string character" << LL_ENDL; + } + setNull(); + return FALSE; + } + + mData[i] = mData[i] << 4; + cur_pos++; + + if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9')) + { + mData[i] += (U8)(in_string[cur_pos] - '0'); + } + else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <= 'f')) + { + mData[i] += (U8)(10 + in_string[cur_pos] - 'a'); + } + else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <= 'F')) + { + mData[i] += (U8)(10 + in_string[cur_pos] - 'A'); + } + else + { + if (emit) + { + LL_WARNS() << "Invalid UUID string character" << LL_ENDL; + } + setNull(); + return FALSE; + } + cur_pos++; + } + + return TRUE; } BOOL LLUUID::validate(const std::string& in_string) { - BOOL broken_format = FALSE; - if (in_string.length() != (UUID_STR_LENGTH - 1)) /* Flawfinder: ignore */ - { - // I'm a moron. First implementation didn't have the right UUID format. - if (in_string.length() == (UUID_STR_LENGTH - 2)) /* Flawfinder: ignore */ - { - broken_format = TRUE; - } - else - { - return FALSE; - } - } - - U8 cur_pos = 0; - for (U32 i = 0; i < 16; i++) - { - if ((i == 4) || (i == 6) || (i == 8) || (i == 10)) - { - cur_pos++; - if (broken_format && (i==10)) - { - // Missing - in the broken format - cur_pos--; - } - } - - if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9')) - { - } - else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <='f')) - { - } - else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <='F')) - { - } - else - { - return FALSE; - } - - cur_pos++; - - if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9')) - { - } - else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <='f')) - { - } - else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <='F')) - { - } - else - { - return FALSE; - } - cur_pos++; - } - return TRUE; + BOOL broken_format = FALSE; + if (in_string.length() != (UUID_STR_LENGTH - 1)) /* Flawfinder: ignore */ + { + // I'm a moron. First implementation didn't have the right UUID format. + if (in_string.length() == (UUID_STR_LENGTH - 2)) /* Flawfinder: ignore */ + { + broken_format = TRUE; + } + else + { + return FALSE; + } + } + + U8 cur_pos = 0; + for (U32 i = 0; i < 16; i++) + { + if ((i == 4) || (i == 6) || (i == 8) || (i == 10)) + { + cur_pos++; + if (broken_format && (i == 10)) + { + // Missing - in the broken format + cur_pos--; + } + } + + if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9')) + { + } + else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <= 'f')) + { + } + else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <= 'F')) + { + } + else + { + return FALSE; + } + + cur_pos++; + + if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9')) + { + } + else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <= 'f')) + { + } + else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <= 'F')) + { + } + else + { + return FALSE; + } + cur_pos++; + } + return TRUE; } const LLUUID& LLUUID::operator^=(const LLUUID& rhs) { - U32* me = (U32*)&(mData[0]); - const U32* other = (U32*)&(rhs.mData[0]); - for(S32 i = 0; i < 4; ++i) - { - me[i] = me[i] ^ other[i]; - } - return *this; + U32* me = (U32*)&(mData[0]); + const U32* other = (U32*)&(rhs.mData[0]); + for (S32 i = 0; i < 4; ++i) + { + me[i] = me[i] ^ other[i]; + } + return *this; } LLUUID LLUUID::operator^(const LLUUID& rhs) const { - LLUUID id(*this); - id ^= rhs; - return id; + LLUUID id(*this); + id ^= rhs; + return id; } -// WARNING: this algorithm SHALL NOT be changed. It is also used by the server -// and plays a role in some assets validation (e.g. clothing items). Changing -// it would cause invalid assets. void LLUUID::combine(const LLUUID& other, LLUUID& result) const { - LLMD5 md5_uuid; - md5_uuid.update((unsigned char*)mData, 16); - md5_uuid.update((unsigned char*)other.mData, 16); - md5_uuid.finalize(); - md5_uuid.raw_digest(result.mData); + LLMD5 md5_uuid; + md5_uuid.update((unsigned char*)mData, 16); + md5_uuid.update((unsigned char*)other.mData, 16); + md5_uuid.finalize(); + md5_uuid.raw_digest(result.mData); } -LLUUID LLUUID::combine(const LLUUID &other) const +LLUUID LLUUID::combine(const LLUUID& other) const { - LLUUID combination; - combine(other, combination); - return combination; + LLUUID combination; + combine(other, combination); + return combination; } -std::ostream& operator<<(std::ostream& s, const LLUUID &uuid) +std::ostream& operator<<(std::ostream& s, const LLUUID& uuid) { - std::string uuid_str; - uuid.toString(uuid_str); - s << uuid_str; - return s; + std::string uuid_str; + uuid.toString(uuid_str); + s << uuid_str; + return s; } -std::istream& operator>>(std::istream &s, LLUUID &uuid) +std::istream& operator>>(std::istream& s, LLUUID& uuid) { - U32 i; - char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */ - for (i = 0; i < UUID_STR_LENGTH-1; i++) - { - s >> uuid_str[i]; - } - uuid_str[i] = '\0'; - uuid.set(std::string(uuid_str)); - return s; + U32 i; + char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */ + for (i = 0; i < UUID_STR_LENGTH - 1; i++) + { + s >> uuid_str[i]; + } + uuid_str[i] = '\0'; + uuid.set(std::string(uuid_str)); + return s; } -static void get_random_bytes(void *buf, int nbytes) +static void get_random_bytes(void* buf, int nbytes) { - int i; - char *cp = (char *) buf; - - // *NOTE: If we are not using the janky generator ll_rand() - // generates at least 3 good bytes of data since it is 0 to - // RAND_MAX. This could be made more efficient by copying all the - // bytes. - for (i=0; i < nbytes; i++) + int i; + char* cp = (char*)buf; + + // *NOTE: If we are not using the janky generator ll_rand() + // generates at least 3 good bytes of data since it is 0 to + // RAND_MAX. This could be made more efficient by copying all the + // bytes. + for (i = 0; i < nbytes; i++) #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR - *cp++ = janky_fast_random_bytes() & 0xFF; + * cp++ = janky_fast_random_bytes() & 0xFF; #else - *cp++ = ll_rand() & 0xFF; + * cp++ = ll_rand() & 0xFF; #endif - return; + return; } #if LL_WINDOWS typedef struct _ASTAT_ { - ADAPTER_STATUS adapt; - NAME_BUFFER NameBuff [30]; + ADAPTER_STATUS adapt; + NAME_BUFFER NameBuff[30]; }ASTAT, * PASTAT; // static -S32 LLUUID::getNodeID(unsigned char *node_id) +S32 LLUUID::getNodeID(unsigned char* node_id) { - ASTAT Adapter; - NCB Ncb; - UCHAR uRetCode; - LANA_ENUM lenum; - int i; - int retval = 0; - - memset( &Ncb, 0, sizeof(Ncb) ); - Ncb.ncb_command = NCBENUM; - Ncb.ncb_buffer = (UCHAR *)&lenum; - Ncb.ncb_length = sizeof(lenum); - uRetCode = Netbios( &Ncb ); - - for(i=0; i < lenum.length ;i++) - { - memset( &Ncb, 0, sizeof(Ncb) ); - Ncb.ncb_command = NCBRESET; - Ncb.ncb_lana_num = lenum.lana[i]; - - uRetCode = Netbios( &Ncb ); - - memset( &Ncb, 0, sizeof (Ncb) ); - Ncb.ncb_command = NCBASTAT; - Ncb.ncb_lana_num = lenum.lana[i]; - - strcpy( (char *)Ncb.ncb_callname, "* " ); /* Flawfinder: ignore */ - Ncb.ncb_buffer = (unsigned char *)&Adapter; - Ncb.ncb_length = sizeof(Adapter); - - uRetCode = Netbios( &Ncb ); - if ( uRetCode == 0 ) - { - memcpy(node_id,Adapter.adapt.adapter_address,6); /* Flawfinder: ignore */ - retval = 1; - } - } - return retval; + ASTAT Adapter; + NCB Ncb; + UCHAR uRetCode; + LANA_ENUM lenum; + int i; + int retval = 0; + + memset(&Ncb, 0, sizeof(Ncb)); + Ncb.ncb_command = NCBENUM; + Ncb.ncb_buffer = (UCHAR*)&lenum; + Ncb.ncb_length = sizeof(lenum); + uRetCode = Netbios(&Ncb); + + for (i = 0; i < lenum.length; i++) + { + memset(&Ncb, 0, sizeof(Ncb)); + Ncb.ncb_command = NCBRESET; + Ncb.ncb_lana_num = lenum.lana[i]; + + uRetCode = Netbios(&Ncb); + + memset(&Ncb, 0, sizeof(Ncb)); + Ncb.ncb_command = NCBASTAT; + Ncb.ncb_lana_num = lenum.lana[i]; + + strcpy((char*)Ncb.ncb_callname, "* "); /* Flawfinder: ignore */ + Ncb.ncb_buffer = (unsigned char*)&Adapter; + Ncb.ncb_length = sizeof(Adapter); + + uRetCode = Netbios(&Ncb); + if (uRetCode == 0) + { + memcpy(node_id, Adapter.adapt.adapter_address, 6); /* Flawfinder: ignore */ + retval = 1; + } + } + return retval; } #elif LL_DARWIN @@ -525,66 +521,66 @@ S32 LLUUID::getNodeID(unsigned char *node_id) #include <net/route.h> #include <ifaddrs.h> -// static -S32 LLUUID::getNodeID(unsigned char *node_id) + // static +S32 LLUUID::getNodeID(unsigned char* node_id) { - int i; - unsigned char *a = NULL; - struct ifaddrs *ifap, *ifa; - int rv; - S32 result = 0; - - if ((rv=getifaddrs(&ifap))==-1) - { - return -1; - } - if (ifap == NULL) - { - return -1; - } - - for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) - { -// printf("Interface %s, address family %d, ", ifa->ifa_name, ifa->ifa_addr->sa_family); - for(i=0; i< ifa->ifa_addr->sa_len; i++) - { -// printf("%02X ", (unsigned char)ifa->ifa_addr->sa_data[i]); - } -// printf("\n"); - - if(ifa->ifa_addr->sa_family == AF_LINK) - { - // This is a link-level address - struct sockaddr_dl *lla = (struct sockaddr_dl *)ifa->ifa_addr; - -// printf("\tLink level address, type %02X\n", lla->sdl_type); - - if(lla->sdl_type == IFT_ETHER) - { - // Use the first ethernet MAC in the list. - // For some reason, the macro LLADDR() defined in net/if_dl.h doesn't expand correctly. This is what it would do. - a = (unsigned char *)&((lla)->sdl_data); - a += (lla)->sdl_nlen; - - if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) - { - continue; - } - - if (node_id) - { - memcpy(node_id, a, 6); - result = 1; - } - - // We found one. - break; - } - } - } - freeifaddrs(ifap); - - return result; + int i; + unsigned char* a = NULL; + struct ifaddrs* ifap, * ifa; + int rv; + S32 result = 0; + + if ((rv = getifaddrs(&ifap)) == -1) + { + return -1; + } + if (ifap == NULL) + { + return -1; + } + + for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) + { + // printf("Interface %s, address family %d, ", ifa->ifa_name, ifa->ifa_addr->sa_family); + for (i = 0; i < ifa->ifa_addr->sa_len; i++) + { + // printf("%02X ", (unsigned char)ifa->ifa_addr->sa_data[i]); + } + // printf("\n"); + + if (ifa->ifa_addr->sa_family == AF_LINK) + { + // This is a link-level address + struct sockaddr_dl* lla = (struct sockaddr_dl*)ifa->ifa_addr; + + // printf("\tLink level address, type %02X\n", lla->sdl_type); + + if (lla->sdl_type == IFT_ETHER) + { + // Use the first ethernet MAC in the list. + // For some reason, the macro LLADDR() defined in net/if_dl.h doesn't expand correctly. This is what it would do. + a = (unsigned char*)&((lla)->sdl_data); + a += (lla)->sdl_nlen; + + if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) + { + continue; + } + + if (node_id) + { + memcpy(node_id, a, 6); + result = 1; + } + + // We found one. + break; + } + } + } + freeifaddrs(ifap); + + return result; } #else @@ -611,22 +607,22 @@ S32 LLUUID::getNodeID(unsigned char *node_id) #endif #endif -// static -S32 LLUUID::getNodeID(unsigned char *node_id) + // static +S32 LLUUID::getNodeID(unsigned char* node_id) { - int sd; - struct ifreq ifr, *ifrp; - struct ifconf ifc; - char buf[1024]; - int n, i; - unsigned char *a; - -/* - * BSD 4.4 defines the size of an ifreq to be - * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len - * However, under earlier systems, sa_len isn't present, so the size is - * just sizeof(struct ifreq) - */ + int sd; + struct ifreq ifr, * ifrp; + struct ifconf ifc; + char buf[1024]; + int n, i; + unsigned char* a; + + /* + * BSD 4.4 defines the size of an ifreq to be + * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len + * However, under earlier systems, sa_len isn't present, so the size is + * just sizeof(struct ifreq) + */ #ifdef HAVE_SA_LEN #ifndef max #define max(a,b) ((a) > (b) ? (a) : (b)) @@ -637,345 +633,356 @@ S32 LLUUID::getNodeID(unsigned char *node_id) #define ifreq_size(i) sizeof(struct ifreq) #endif /* HAVE_SA_LEN*/ - sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); - if (sd < 0) { - return -1; - } - memset(buf, 0, sizeof(buf)); - ifc.ifc_len = sizeof(buf); - ifc.ifc_buf = buf; - if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) { - close(sd); - return -1; - } - n = ifc.ifc_len; - for (i = 0; i < n; i+= ifreq_size(*ifr) ) { - ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i); - strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); /* Flawfinder: ignore */ + sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (sd < 0) { + return -1; + } + memset(buf, 0, sizeof(buf)); + ifc.ifc_len = sizeof(buf); + ifc.ifc_buf = buf; + if (ioctl(sd, SIOCGIFCONF, (char*)&ifc) < 0) { + close(sd); + return -1; + } + n = ifc.ifc_len; + for (i = 0; i < n; i += ifreq_size(*ifr)) { + ifrp = (struct ifreq*)((char*)ifc.ifc_buf + i); + strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); /* Flawfinder: ignore */ #ifdef SIOCGIFHWADDR - if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) - continue; - a = (unsigned char *) &ifr.ifr_hwaddr.sa_data; + if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) + continue; + a = (unsigned char*)&ifr.ifr_hwaddr.sa_data; #else #ifdef SIOCGENADDR - if (ioctl(sd, SIOCGENADDR, &ifr) < 0) - continue; - a = (unsigned char *) ifr.ifr_enaddr; + if (ioctl(sd, SIOCGENADDR, &ifr) < 0) + continue; + a = (unsigned char*)ifr.ifr_enaddr; #else - /* - * XXX we don't have a way of getting the hardware - * address - */ - close(sd); - return 0; + /* + * XXX we don't have a way of getting the hardware + * address + */ + close(sd); + return 0; #endif /* SIOCGENADDR */ #endif /* SIOCGIFHWADDR */ - if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) - continue; - if (node_id) { - memcpy(node_id, a, 6); /* Flawfinder: ignore */ - close(sd); - return 1; - } - } - close(sd); - return 0; + if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) + continue; + if (node_id) { + memcpy(node_id, a, 6); /* Flawfinder: ignore */ + close(sd); + return 1; + } + } + close(sd); + return 0; } #endif -S32 LLUUID::cmpTime(uuid_time_t *t1, uuid_time_t *t2) +S32 LLUUID::cmpTime(uuid_time_t* t1, uuid_time_t* t2) { - // Compare two time values. + // Compare two time values. - if (t1->high < t2->high) return -1; - if (t1->high > t2->high) return 1; - if (t1->low < t2->low) return -1; - if (t1->low > t2->low) return 1; - return 0; + if (t1->high < t2->high) return -1; + if (t1->high > t2->high) return 1; + if (t1->low < t2->low) return -1; + if (t1->low > t2->low) return 1; + return 0; } -void LLUUID::getSystemTime(uuid_time_t *timestamp) +void LLUUID::getSystemTime(uuid_time_t* timestamp) { - // Get system time with 100ns precision. Time is since Oct 15, 1582. + // Get system time with 100ns precision. Time is since Oct 15, 1582. #if LL_WINDOWS - ULARGE_INTEGER time; - GetSystemTimeAsFileTime((FILETIME *)&time); - // NT keeps time in FILETIME format which is 100ns ticks since - // Jan 1, 1601. UUIDs use time in 100ns ticks since Oct 15, 1582. - // The difference is 17 Days in Oct + 30 (Nov) + 31 (Dec) - // + 18 years and 5 leap days. - time.QuadPart += - (unsigned __int64) (1000*1000*10) // seconds - * (unsigned __int64) (60 * 60 * 24) // days - * (unsigned __int64) (17+30+31+365*18+5); // # of days - - timestamp->high = time.HighPart; - timestamp->low = time.LowPart; + ULARGE_INTEGER time; + GetSystemTimeAsFileTime((FILETIME*)&time); + // NT keeps time in FILETIME format which is 100ns ticks since + // Jan 1, 1601. UUIDs use time in 100ns ticks since Oct 15, 1582. + // The difference is 17 Days in Oct + 30 (Nov) + 31 (Dec) + // + 18 years and 5 leap days. + time.QuadPart += + (unsigned __int64)(1000 * 1000 * 10) // seconds + * (unsigned __int64)(60 * 60 * 24) // days + * (unsigned __int64)(17 + 30 + 31 + 365 * 18 + 5); // # of days + + timestamp->high = time.HighPart; + timestamp->low = time.LowPart; #else - struct timeval tp; - gettimeofday(&tp, 0); - - // Offset between UUID formatted times and Unix formatted times. - // UUID UTC base time is October 15, 1582. - // Unix base time is January 1, 1970. - U64 uuid_time = ((U64)tp.tv_sec * 10000000) + (tp.tv_usec * 10) + - U64L(0x01B21DD213814000); - timestamp->high = (U32) (uuid_time >> 32); - timestamp->low = (U32) (uuid_time & 0xFFFFFFFF); + struct timeval tp; + gettimeofday(&tp, 0); + + // Offset between UUID formatted times and Unix formatted times. + // UUID UTC base time is October 15, 1582. + // Unix base time is January 1, 1970. + U64 uuid_time = ((U64)tp.tv_sec * 10000000) + (tp.tv_usec * 10) + + U64L(0x01B21DD213814000); + timestamp->high = (U32)(uuid_time >> 32); + timestamp->low = (U32)(uuid_time & 0xFFFFFFFF); #endif } -void LLUUID::getCurrentTime(uuid_time_t *timestamp) +void LLUUID::getCurrentTime(uuid_time_t* timestamp) { - // Get current time as 60 bit 100ns ticks since whenever. - // Compensate for the fact that real clock resolution is less - // than 100ns. - - const U32 uuids_per_tick = 1024; - - static uuid_time_t time_last; - static U32 uuids_this_tick; - static BOOL init = FALSE; - - if (!init) { - getSystemTime(&time_last); - uuids_this_tick = uuids_per_tick; - init = TRUE; - mMutex = new LLMutex(); - } - - uuid_time_t time_now = {0,0}; - - while (1) { - getSystemTime(&time_now); - - // if clock reading changed since last UUID generated - if (cmpTime(&time_last, &time_now)) { - // reset count of uuid's generated with this clock reading - uuids_this_tick = 0; - break; - } - if (uuids_this_tick < uuids_per_tick) { - uuids_this_tick++; - break; - } - // going too fast for our clock; spin - } - - time_last = time_now; - - if (uuids_this_tick != 0) { - if (time_now.low & 0x80000000) { - time_now.low += uuids_this_tick; - if (!(time_now.low & 0x80000000)) - time_now.high++; - } else - time_now.low += uuids_this_tick; - } - - timestamp->high = time_now.high; - timestamp->low = time_now.low; + // Get current time as 60 bit 100ns ticks since whenever. + // Compensate for the fact that real clock resolution is less + // than 100ns. + + const U32 uuids_per_tick = 1024; + + static uuid_time_t time_last; + static U32 uuids_this_tick; + static BOOL init = FALSE; + + if (!init) { + getSystemTime(&time_last); + uuids_this_tick = uuids_per_tick; + init = TRUE; + mMutex = new LLMutex(); + } + + uuid_time_t time_now = { 0,0 }; + + while (1) { + getSystemTime(&time_now); + + // if clock reading changed since last UUID generated + if (cmpTime(&time_last, &time_now)) { + // reset count of uuid's generated with this clock reading + uuids_this_tick = 0; + break; + } + if (uuids_this_tick < uuids_per_tick) { + uuids_this_tick++; + break; + } + // going too fast for our clock; spin + } + + time_last = time_now; + + if (uuids_this_tick != 0) { + if (time_now.low & 0x80000000) { + time_now.low += uuids_this_tick; + if (!(time_now.low & 0x80000000)) + time_now.high++; + } + else + time_now.low += uuids_this_tick; + } + + timestamp->high = time_now.high; + timestamp->low = time_now.low; } void LLUUID::generate() { - // Create a UUID. - uuid_time_t timestamp; - - static unsigned char node_id[6]; /* Flawfinder: ignore */ - static int has_init = 0; - - // Create a UUID. - static uuid_time_t time_last = {0,0}; - static U16 clock_seq = 0; + // Create a UUID. + uuid_time_t timestamp; + + static unsigned char node_id[6]; /* Flawfinder: ignore */ + static int has_init = 0; + + // Create a UUID. + static uuid_time_t time_last = { 0,0 }; + static U16 clock_seq = 0; #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR - static U32 seed = 0L; // dummy seed. reset it below + static U32 seed = 0L; // dummy seed. reset it below #endif - if (!has_init) - { - has_init = 1; - if (getNodeID(node_id) <= 0) - { - get_random_bytes(node_id, 6); - /* - * Set multicast bit, to prevent conflicts - * with IEEE 802 addresses obtained from - * network cards - */ - node_id[0] |= 0x80; - } - - getCurrentTime(&time_last); + if (!has_init) + { + has_init = 1; + if (getNodeID(node_id) <= 0) + { + get_random_bytes(node_id, 6); + /* + * Set multicast bit, to prevent conflicts + * with IEEE 802 addresses obtained from + * network cards + */ + node_id[0] |= 0x80; + } + + getCurrentTime(&time_last); #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR - seed = time_last.low; + seed = time_last.low; #endif #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR - clock_seq = (U16)janky_fast_random_seeded_bytes(seed, 65536); + clock_seq = (U16)janky_fast_random_seeded_bytes(seed, 65536); #else - clock_seq = (U16)ll_rand(65536); + clock_seq = (U16)ll_rand(65536); #endif - } - - // get current time - getCurrentTime(×tamp); - U16 our_clock_seq = clock_seq; - - // if clock hasn't changed or went backward, change clockseq - if (cmpTime(×tamp, &time_last) != 1) - { - LLMutexLock lock(mMutex); - clock_seq = (clock_seq + 1) & 0x3FFF; - if (clock_seq == 0) - clock_seq++; - our_clock_seq = clock_seq; // Ensure we're using a different clock_seq value from previous time - } + } + + // get current time + getCurrentTime(×tamp); + U16 our_clock_seq = clock_seq; + + // if clock hasn't changed or went backward, change clockseq + if (cmpTime(×tamp, &time_last) != 1) + { + LLMutexLock lock(mMutex); + clock_seq = (clock_seq + 1) & 0x3FFF; + if (clock_seq == 0) + clock_seq++; + our_clock_seq = clock_seq; // Ensure we're using a different clock_seq value from previous time + } time_last = timestamp; - memcpy(mData+10, node_id, 6); /* Flawfinder: ignore */ - U32 tmp; - tmp = timestamp.low; - mData[3] = (unsigned char) tmp; - tmp >>= 8; - mData[2] = (unsigned char) tmp; - tmp >>= 8; - mData[1] = (unsigned char) tmp; - tmp >>= 8; - mData[0] = (unsigned char) tmp; - - tmp = (U16) timestamp.high; - mData[5] = (unsigned char) tmp; - tmp >>= 8; - mData[4] = (unsigned char) tmp; - - tmp = (timestamp.high >> 16) | 0x1000; - mData[7] = (unsigned char) tmp; - tmp >>= 8; - mData[6] = (unsigned char) tmp; - - tmp = our_clock_seq; - - mData[9] = (unsigned char) tmp; - tmp >>= 8; - mData[8] = (unsigned char) tmp; - - HBXXH128::digest(*this, (const void*)mData, 16); + memcpy(mData + 10, node_id, 6); /* Flawfinder: ignore */ + U32 tmp; + tmp = timestamp.low; + mData[3] = (unsigned char)tmp; + tmp >>= 8; + mData[2] = (unsigned char)tmp; + tmp >>= 8; + mData[1] = (unsigned char)tmp; + tmp >>= 8; + mData[0] = (unsigned char)tmp; + + tmp = (U16)timestamp.high; + mData[5] = (unsigned char)tmp; + tmp >>= 8; + mData[4] = (unsigned char)tmp; + + tmp = (timestamp.high >> 16) | 0x1000; + mData[7] = (unsigned char)tmp; + tmp >>= 8; + mData[6] = (unsigned char)tmp; + + tmp = our_clock_seq; + + mData[9] = (unsigned char)tmp; + tmp >>= 8; + mData[8] = (unsigned char)tmp; + + LLMD5 md5_uuid; + + md5_uuid.update(mData, 16); + md5_uuid.finalize(); + md5_uuid.raw_digest(mData); } void LLUUID::generate(const std::string& hash_string) { - HBXXH128::digest(*this, hash_string); + LLMD5 md5_uuid((U8*)hash_string.c_str()); + md5_uuid.raw_digest(mData); } U32 LLUUID::getRandomSeed() { - static unsigned char seed[16]; /* Flawfinder: ignore */ - - getNodeID(&seed[0]); + static unsigned char seed[16]; /* Flawfinder: ignore */ - // Incorporate the pid into the seed to prevent - // processes that start on the same host at the same - // time from generating the same seed. - pid_t pid = LLApp::getPid(); + getNodeID(&seed[0]); - seed[6]=(unsigned char)(pid >> 8); - seed[7]=(unsigned char)(pid); - getSystemTime((uuid_time_t *)(&seed[8])); + // Incorporate the pid into the seed to prevent + // processes that start on the same host at the same + // time from generating the same seed. + pid_t pid = LLApp::getPid(); - U64 seed64 = HBXXH64((const void*)seed, 16).digest(); - return U32(seed64) ^ U32(seed64 >> 32); + seed[6] = (unsigned char)(pid >> 8); + seed[7] = (unsigned char)(pid); + getSystemTime((uuid_time_t*)(&seed[8])); + + LLMD5 md5_seed; + + md5_seed.update(seed, 16); + md5_seed.finalize(); + md5_seed.raw_digest(seed); + + return(*(U32*)seed); } BOOL LLUUID::parseUUID(const std::string& buf, LLUUID* value) { - if( buf.empty() || value == NULL) - { - return FALSE; - } - - std::string temp( buf ); - LLStringUtil::trim(temp); - if( LLUUID::validate( temp ) ) - { - value->set( temp ); - return TRUE; - } - return FALSE; + if (buf.empty() || value == NULL) + { + return FALSE; + } + + std::string temp(buf); + LLStringUtil::trim(temp); + if (LLUUID::validate(temp)) + { + value->set(temp); + return TRUE; + } + return FALSE; } //static LLUUID LLUUID::generateNewID(std::string hash_string) { - LLUUID new_id; - if (hash_string.empty()) - { - new_id.generate(); - } - else - { - new_id.generate(hash_string); - } - return new_id; + LLUUID new_id; + if (hash_string.empty()) + { + new_id.generate(); + } + else + { + new_id.generate(hash_string); + } + return new_id; } LLAssetID LLTransactionID::makeAssetID(const LLUUID& session) const { - LLAssetID result; - if (isNull()) - { - result.setNull(); - } - else - { - combine(session, result); - } - return result; + LLAssetID result; + if (isNull()) + { + result.setNull(); + } + else + { + combine(session, result); + } + return result; } // Construct LLUUID::LLUUID() { - setNull(); + setNull(); } // Faster than copying from memory - void LLUUID::setNull() +void LLUUID::setNull() { - U32 *word = (U32 *)mData; - word[0] = 0; - word[1] = 0; - word[2] = 0; - word[3] = 0; + U32* word = (U32*)mData; + word[0] = 0; + word[1] = 0; + word[2] = 0; + word[3] = 0; } // Compare - bool LLUUID::operator==(const LLUUID& rhs) const +bool LLUUID::operator==(const LLUUID& rhs) const { - U32 *tmp = (U32 *)mData; - U32 *rhstmp = (U32 *)rhs.mData; - // Note: binary & to avoid branching - return - (tmp[0] == rhstmp[0]) & - (tmp[1] == rhstmp[1]) & - (tmp[2] == rhstmp[2]) & - (tmp[3] == rhstmp[3]); + U32* tmp = (U32*)mData; + U32* rhstmp = (U32*)rhs.mData; + // Note: binary & to avoid branching + return + (tmp[0] == rhstmp[0]) & + (tmp[1] == rhstmp[1]) & + (tmp[2] == rhstmp[2]) & + (tmp[3] == rhstmp[3]); } - bool LLUUID::operator!=(const LLUUID& rhs) const +bool LLUUID::operator!=(const LLUUID& rhs) const { - U32 *tmp = (U32 *)mData; - U32 *rhstmp = (U32 *)rhs.mData; - // Note: binary | to avoid branching - return - (tmp[0] != rhstmp[0]) | - (tmp[1] != rhstmp[1]) | - (tmp[2] != rhstmp[2]) | - (tmp[3] != rhstmp[3]); + U32* tmp = (U32*)mData; + U32* rhstmp = (U32*)rhs.mData; + // Note: binary | to avoid branching + return + (tmp[0] != rhstmp[0]) | + (tmp[1] != rhstmp[1]) | + (tmp[2] != rhstmp[2]) | + (tmp[3] != rhstmp[3]); } /* @@ -983,94 +990,94 @@ LLUUID::LLUUID() // to integers, among other things. Use isNull() or notNull(). LLUUID::operator bool() const { - U32 *word = (U32 *)mData; - return (word[0] | word[1] | word[2] | word[3]) > 0; + U32 *word = (U32 *)mData; + return (word[0] | word[1] | word[2] | word[3]) > 0; } */ - BOOL LLUUID::notNull() const +BOOL LLUUID::notNull() const { - U32 *word = (U32 *)mData; - return (word[0] | word[1] | word[2] | word[3]) > 0; + U32* word = (U32*)mData; + return (word[0] | word[1] | word[2] | word[3]) > 0; } // Faster than == LLUUID::null because doesn't require // as much memory access. - BOOL LLUUID::isNull() const +BOOL LLUUID::isNull() const { - U32 *word = (U32 *)mData; - // If all bits are zero, return !0 == TRUE - return !(word[0] | word[1] | word[2] | word[3]); + U32* word = (U32*)mData; + // If all bits are zero, return !0 == TRUE + return !(word[0] | word[1] | word[2] | word[3]); } - LLUUID::LLUUID(const char *in_string) +LLUUID::LLUUID(const char* in_string) { - if (!in_string || in_string[0] == 0) - { - setNull(); - return; - } - - set(in_string); + if (!in_string || in_string[0] == 0) + { + setNull(); + return; + } + + set(in_string); } - LLUUID::LLUUID(const std::string& in_string) +LLUUID::LLUUID(const std::string& in_string) { - if (in_string.empty()) - { - setNull(); - return; - } + if (in_string.empty()) + { + setNull(); + return; + } - set(in_string); + set(in_string); } // IW: DON'T "optimize" these w/ U32s or you'll scoogie the sort order // IW: this will make me very sad - bool LLUUID::operator<(const LLUUID &rhs) const +bool LLUUID::operator<(const LLUUID& rhs) const { - U32 i; - for( i = 0; i < (UUID_BYTES - 1); i++ ) - { - if( mData[i] != rhs.mData[i] ) - { - return (mData[i] < rhs.mData[i]); - } - } - return (mData[UUID_BYTES - 1] < rhs.mData[UUID_BYTES - 1]); + U32 i; + for (i = 0; i < (UUID_BYTES - 1); i++) + { + if (mData[i] != rhs.mData[i]) + { + return (mData[i] < rhs.mData[i]); + } + } + return (mData[UUID_BYTES - 1] < rhs.mData[UUID_BYTES - 1]); } - bool LLUUID::operator>(const LLUUID &rhs) const +bool LLUUID::operator>(const LLUUID& rhs) const { - U32 i; - for( i = 0; i < (UUID_BYTES - 1); i++ ) - { - if( mData[i] != rhs.mData[i] ) - { - return (mData[i] > rhs.mData[i]); - } - } - return (mData[UUID_BYTES - 1] > rhs.mData[UUID_BYTES - 1]); + U32 i; + for (i = 0; i < (UUID_BYTES - 1); i++) + { + if (mData[i] != rhs.mData[i]) + { + return (mData[i] > rhs.mData[i]); + } + } + return (mData[UUID_BYTES - 1] > rhs.mData[UUID_BYTES - 1]); } - U16 LLUUID::getCRC16() const +U16 LLUUID::getCRC16() const { - // A UUID is 16 bytes, or 8 shorts. - U16 *short_data = (U16*)mData; - U16 out = 0; - out += short_data[0]; - out += short_data[1]; - out += short_data[2]; - out += short_data[3]; - out += short_data[4]; - out += short_data[5]; - out += short_data[6]; - out += short_data[7]; - return out; + // A UUID is 16 bytes, or 8 shorts. + U16* short_data = (U16*)mData; + U16 out = 0; + out += short_data[0]; + out += short_data[1]; + out += short_data[2]; + out += short_data[3]; + out += short_data[4]; + out += short_data[5]; + out += short_data[6]; + out += short_data[7]; + return out; } - U32 LLUUID::getCRC32() const +U32 LLUUID::getCRC32() const { - U32 *tmp = (U32*)mData; - return tmp[0] + tmp[1] + tmp[2] + tmp[3]; + U32* tmp = (U32*)mData; + return tmp[0] + tmp[1] + tmp[2] + tmp[3]; } diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 9919af5368..7a694ab10c 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -4863,17 +4863,6 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) mTangents = NULL; } - if (src.mTangents) - { - allocateTangents(src.mNumVertices); - LLVector4a::memcpyNonAliased16((F32*)mTangents, (F32*)src.mTangents, vert_size); - } - else - { - ll_aligned_free_16(mTangents); - mTangents = nullptr; - } - if (src.mWeights) { llassert(!mWeights); // don't orphan an old alloc here accidentally diff --git a/indra/llprimitive/llgltfloader.cpp b/indra/llprimitive/llgltfloader.cpp index fd304f7bc9..7394f99794 100644 --- a/indra/llprimitive/llgltfloader.cpp +++ b/indra/llprimitive/llgltfloader.cpp @@ -106,10 +106,12 @@ bool LLGLTFLoader::OpenFile(const std::string &filename) tinygltf::TinyGLTF loader; std::string error_msg; std::string warn_msg; + std::string filename_lc(filename); + LLStringUtil::toLower(filename_lc); // Load a tinygltf model fom a file. Assumes that the input filename has already been // been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish. - if (std::string::npos == filename.rfind(".gltf")) + if (std::string::npos == filename_lc.rfind(".gltf")) { // file is binary mGltfLoaded = loader.LoadBinaryFromFile(&mGltfModel, &error_msg, &warn_msg, filename); } diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h index e701b62fdc..b453b91e67 100644 --- a/indra/llprimitive/llgltfmaterial.h +++ b/indra/llprimitive/llgltfmaterial.h @@ -98,7 +98,8 @@ public: std::array<TextureTransform, GLTF_TEXTURE_INFO_COUNT> mTextureTransform; - // NOTE : initialize values to defaults according to the GLTF spec + // NOTE: initialize values to defaults according to the GLTF spec + // NOTE: these values should be in linear color space LLColor4 mBaseColor = LLColor4(1, 1, 1, 1); LLColor3 mEmissiveColor = LLColor3(0, 0, 0); diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp index 52118172c0..ac48a633c7 100644 --- a/indra/llrender/llcubemaparray.cpp +++ b/indra/llrender/llcubemaparray.cpp @@ -122,7 +122,7 @@ void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, BOOL us bind(0); - U32 format = components == 4 ? GL_RGBA12 : GL_RGB10; + U32 format = components == 4 ? GL_RGBA12 : GL_RGB16F; U32 mip = 0; diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h index 8cfe7b62de..3732333f8f 100644 --- a/indra/llrender/llgltexture.h +++ b/indra/llrender/llgltexture.h @@ -49,10 +49,8 @@ public: enum EBoostLevel { BOOST_NONE = 0, - BOOST_ALM , //acts like NONE when ALM is on, max discard when ALM is off BOOST_AVATAR_BAKED , BOOST_AVATAR , - BOOST_CLOUDS , BOOST_SCULPTED , BOOST_HIGH = 10, diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 50d4532fa7..b5c36ea35e 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1409,52 +1409,59 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt free_cur_tex_image(); #if LL_DARWIN - { - LL_PROFILE_ZONE_NAMED("glTexImage2D alloc"); - glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels); - } + const bool use_sub_image = false; #else - // break up calls to a manageable size for the GL command buffer + // glTexSubImage2D doesn't work with compressed textures on select tested Nvidia GPUs on Windows 10 -Cosmic,2023-03-08 + const bool use_sub_image = !allow_compression; +#endif + if (!use_sub_image) { LL_PROFILE_ZONE_NAMED("glTexImage2D alloc"); - glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, nullptr); + glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels); } - - U8* src = (U8*)(use_scratch ? scratch : pixels); - if (src) + else { - LL_PROFILE_ZONE_NAMED("glTexImage2D copy"); - U32 components = dataFormatComponents(pixformat); - U32 type_width = 0; - - switch (pixtype) + // break up calls to a manageable size for the GL command buffer { - case GL_UNSIGNED_BYTE: - case GL_BYTE: - case GL_UNSIGNED_INT_8_8_8_8_REV: - type_width = 1; - break; - case GL_UNSIGNED_SHORT: - case GL_SHORT: - type_width = 2; - break; - case GL_UNSIGNED_INT: - case GL_INT: - case GL_FLOAT: - type_width = 4; - break; - default: - LL_ERRS() << "Unknown type: " << pixtype << LL_ENDL; + LL_PROFILE_ZONE_NAMED("glTexImage2D alloc"); + glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, nullptr); } - U32 line_width = width * components * type_width; - for (U32 y = 0; y < height; ++y) + U8* src = (U8*)(use_scratch ? scratch : pixels); + if (src) { - glTexSubImage2D(target, miplevel, 0, y, width, 1, pixformat, pixtype, src); - src += line_width; + LL_PROFILE_ZONE_NAMED("glTexImage2D copy"); + U32 components = dataFormatComponents(pixformat); + U32 type_width = 0; + + switch (pixtype) + { + case GL_UNSIGNED_BYTE: + case GL_BYTE: + case GL_UNSIGNED_INT_8_8_8_8_REV: + type_width = 1; + break; + case GL_UNSIGNED_SHORT: + case GL_SHORT: + type_width = 2; + break; + case GL_UNSIGNED_INT: + case GL_INT: + case GL_FLOAT: + type_width = 4; + break; + default: + LL_ERRS() << "Unknown type: " << pixtype << LL_ENDL; + } + + U32 line_width = width * components * type_width; + for (U32 y = 0; y < height; ++y) + { + glTexSubImage2D(target, miplevel, 0, y, width, 1, pixformat, pixtype, src); + src += line_width; + } } } -#endif alloc_tex_image(width, height, pixformat); } stop_glerror(); diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index bbd024abd9..a03233323b 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -118,6 +118,9 @@ public: BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0, bool defer_copy = false, LLGLuint* tex_name = nullptr); void setImage(const LLImageRaw* imageraw); BOOL setImage(const U8* data_in, BOOL data_hasmips = FALSE, S32 usename = 0); + // *NOTE: force_fast_update should only be used if the texture is not + // compressed (i.e. RenderCompressTextures is 0). Partial image updates + // (glTexSubImage2D) do not work on compressed textures. BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE, LLGLuint use_name = 0); BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE, LLGLuint use_name = 0); BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index de74f2700a..8430d13093 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -70,9 +70,6 @@ bool LLRender::sGLCoreProfile = false; bool LLRender::sNsightDebugSupport = false; LLVector2 LLRender::sUIGLScaleFactor = LLVector2(1.f, 1.f); -static const U32 LL_NUM_TEXTURE_LAYERS = 32; -static const U32 LL_NUM_LIGHT_UNITS = 8; - struct LLVBCache { LLPointer<LLVertexBuffer> vb; @@ -823,16 +820,14 @@ LLRender::LLRender() mMode(LLRender::TRIANGLES), mCurrTextureUnitIndex(0) { - mTexUnits.reserve(LL_NUM_TEXTURE_LAYERS); for (U32 i = 0; i < LL_NUM_TEXTURE_LAYERS; i++) { - mTexUnits.push_back(new LLTexUnit(i)); + mTexUnits[i].mIndex = i; } - mDummyTexUnit = new LLTexUnit(-1); for (U32 i = 0; i < LL_NUM_LIGHT_UNITS; ++i) { - mLightState.push_back(new LLLightState(i)); + mLightState[i].mIndex = i; } for (U32 i = 0; i < 4; i++) @@ -915,19 +910,6 @@ void LLRender::resetVertexBuffer() void LLRender::shutdown() { - for (U32 i = 0; i < mTexUnits.size(); i++) - { - delete mTexUnits[i]; - } - mTexUnits.clear(); - delete mDummyTexUnit; - mDummyTexUnit = NULL; - - for (U32 i = 0; i < mLightState.size(); ++i) - { - delete mLightState[i]; - } - mLightState.clear(); resetVertexBuffer(); } @@ -939,10 +921,10 @@ void LLRender::refreshState(void) for (U32 i = 0; i < mTexUnits.size(); i++) { - mTexUnits[i]->refreshState(); + mTexUnits[i].refreshState(); } - mTexUnits[active_unit]->activate(); + mTexUnits[active_unit].activate(); setColorMask(mCurrColorMask[0], mCurrColorMask[1], mCurrColorMask[2], mCurrColorMask[3]); @@ -974,7 +956,7 @@ void LLRender::syncLightState() for (U32 i = 0; i < LL_NUM_LIGHT_UNITS; i++) { - LLLightState *light = mLightState[i]; + LLLightState *light = &mLightState[i]; position[i] = light->mPosition; direction[i] = light->mSpotDirection; @@ -992,7 +974,7 @@ void LLRender::syncLightState() shader->uniform3fv(LLShaderMgr::LIGHT_DIFFUSE, LL_NUM_LIGHT_UNITS, diffuse[0].mV); shader->uniform3fv(LLShaderMgr::LIGHT_AMBIENT, 1, mAmbientLightColor.mV); shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_primary[0] ? 1 : 0); - shader->uniform3fv(LLShaderMgr::AMBIENT, 1, mAmbientLightColor.mV); + //shader->uniform3fv(LLShaderMgr::AMBIENT, 1, mAmbientLightColor.mV); shader->uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, 1, diffuse[0].mV); shader->uniform3fv(LLShaderMgr::MOONLIGHT_COLOR, 1, diffuse_b[0].mV); } @@ -1501,12 +1483,12 @@ LLTexUnit* LLRender::getTexUnit(U32 index) { if (index < mTexUnits.size()) { - return mTexUnits[index]; + return &mTexUnits[index]; } else { LL_DEBUGS() << "Non-existing texture unit layer requested: " << index << LL_ENDL; - return mDummyTexUnit; + return &mDummyTexUnit; } } @@ -1514,7 +1496,7 @@ LLLightState* LLRender::getLight(U32 index) { if (index < mLightState.size()) { - return mLightState[index]; + return &mLightState[index]; } return NULL; diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index e8baf6bb7e..6f61627235 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -52,6 +52,9 @@ class LLTexture ; #define LL_MATRIX_STACK_DEPTH 32 +constexpr U32 LL_NUM_TEXTURE_LAYERS = 32; +constexpr U32 LL_NUM_LIGHT_UNITS = 8; + class LLTexUnit { friend class LLRender; @@ -135,7 +138,7 @@ public: TCS_SRGB } eTextureColorSpace; - LLTexUnit(S32 index); + LLTexUnit(S32 index = -1); // Refreshes renderer state of the texture unit to the cached values // Needed when the render context has changed and invalidated the current state @@ -212,7 +215,9 @@ public: eTextureColorSpace getCurrColorSpace() { return mTexColorSpace; } protected: - const S32 mIndex; + friend class LLRender; + + S32 mIndex; U32 mCurrTexture; eTextureType mCurrTexType; eTextureColorSpace mTexColorSpace; @@ -230,7 +235,7 @@ protected: class LLLightState { public: - LLLightState(S32 index); + LLLightState(S32 index = -1); void enable(); void disable(); @@ -488,9 +493,9 @@ private: LLStrider<LLVector3> mVerticesp; LLStrider<LLVector2> mTexcoordsp; LLStrider<LLColor4U> mColorsp; - std::vector<LLTexUnit*> mTexUnits; - LLTexUnit* mDummyTexUnit; - std::vector<LLLightState*> mLightState; + std::array<LLTexUnit, LL_NUM_TEXTURE_LAYERS> mTexUnits; + LLTexUnit mDummyTexUnit; + std::array<LLLightState, LL_NUM_LIGHT_UNITS> mLightState; eBlendFactor mCurrBlendColorSFactor; eBlendFactor mCurrBlendColorDFactor; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 6fb319fd5b..08a2e6779e 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -188,7 +188,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) /////////////////////////////////////// // NOTE order of shader object attaching is VERY IMPORTANT!!! - if (features->hasSrgb || features->hasAtmospherics || features->calculatesAtmospherics) + if (features->hasSrgb || features->hasAtmospherics || features->calculatesAtmospherics || features->isDeferred) { if (!shader->attachFragmentObject("environment/srgbF.glsl")) { diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 2fe80af373..dd0ea0096c 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -314,13 +314,16 @@ public: U32 mTouchCount = 0; -#if ANALYZE_VBO_POOL U64 mDistributed = 0; U64 mAllocated = 0; U64 mReserved = 0; U32 mMisses = 0; U32 mHits = 0; -#endif + + U64 getVramBytesUsed() + { + return mAllocated + mReserved; + } // increase the size to some common value (e.g. a power of two) to increase hit rate void adjustSize(U32& size) @@ -341,13 +344,9 @@ public: llassert(data == nullptr); // non null data indicates a buffer that wasn't freed llassert(size >= 2); // any buffer size smaller than a single index is nonsensical -#if ANALYZE_VBO_POOL mDistributed += size; adjustSize(size); mAllocated += size; -#else - adjustSize(size); -#endif auto& pool = type == GL_ELEMENT_ARRAY_BUFFER ? mIBOPool : mVBOPool; @@ -357,9 +356,7 @@ public: LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vbo pool miss"); LL_PROFILE_GPU_ZONE("vbo alloc"); -#if ANALYZE_VBO_POOL mMisses++; -#endif name = gen_buffer(); glBindBuffer(type, name); glBufferData(type, size, nullptr, GL_DYNAMIC_DRAW); @@ -376,11 +373,9 @@ public: } else { -#if ANALYZE_VBO_POOL mHits++; llassert(mReserved >= size); // assert if accounting gets messed up mReserved -= size; -#endif std::list<Entry>& entries = iter->second; Entry& entry = entries.back(); @@ -407,16 +402,12 @@ public: clean(); -#if ANALYZE_VBO_POOL llassert(mDistributed >= size); mDistributed -= size; adjustSize(size); llassert(mAllocated >= size); mAllocated -= size; mReserved += size; -#else - adjustSize(size); -#endif auto& pool = type == GL_ELEMENT_ARRAY_BUFFER ? mIBOPool : mVBOPool; @@ -465,10 +456,8 @@ public: auto& entry = entries.back(); ll_aligned_free_16(entry.mData); glDeleteBuffers(1, &entry.mGLName); -#if ANALYZE_VBO_POOL llassert(mReserved >= iter->first); mReserved -= iter->first; -#endif entries.pop_back(); } @@ -484,7 +473,7 @@ public: } } -#if ANALYZE_VBO_POOL +#if 0 LL_INFOS() << llformat("(%d/%d)/%d MB (distributed/allocated)/total in VBO Pool. Overhead: %d percent. Hit rate: %d percent", mDistributed / 1000000, mAllocated / 1000000, @@ -515,9 +504,7 @@ public: } } -#if ANALYZE_VBO_POOL mReserved = 0; -#endif mIBOPool.clear(); mVBOPool.clear(); @@ -528,6 +515,12 @@ public: static LLVBOPool* sVBOPool = nullptr; +//static +U64 LLVertexBuffer::getBytesAllocated() +{ + return sVBOPool ? sVBOPool->getVramBytesUsed() : 0; +} + //============================================================================ // //static @@ -1363,7 +1356,9 @@ void LLVertexBuffer::setBuffer() U32 data_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask; // this Vertex Buffer must provide all necessary attributes for currently bound shader - //llassert((data_mask & mTypeMask) == data_mask); + llassert_msg((data_mask & mTypeMask) == data_mask, + "Attribute mask mismatch! mTypeMask should be a superset of data_mask. data_mask: 0x" + << std::hex << data_mask << " mTypeMask: 0x" << mTypeMask << " Missing: 0x" << (data_mask & ~mTypeMask) << std::dec); if (sGLRenderBuffer != mGLBuffer) { diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 571856f013..f2d146d4bb 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -256,6 +256,8 @@ private: bool allocateBuffer(S32 nverts, S32 nindices, BOOL create) { return allocateBuffer(nverts, nindices); } public: + + static U64 getBytesAllocated(); static const U32 sTypeSize[TYPE_MAX]; static const U32 sGLMode[LLRender::NUM_MODES]; static U32 sGLRenderBuffer; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 10cf7513b5..666adcf672 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -4857,13 +4857,14 @@ void LLWindowWin32::LLWindowWin32Thread::updateVRAMUsage() DXGI_QUERY_VIDEO_MEMORY_INFO info; mDXGIAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &info); - #if 0 // debug 0 budget and 0 CU info.Budget = 0; info.CurrentUsage = 0; #endif U32 budget_mb = info.Budget / 1024 / 1024; + gGLManager.mVRAM = llmax(gGLManager.mVRAM, (S32) budget_mb); + U32 afr_mb = info.AvailableForReservation / 1024 / 1024; // correct for systems that misreport budget if (budget_mb == 0) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 81fed560bb..a369b22ef1 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10402,7 +10402,7 @@ <key>Type</key> <string>F32</string> <key>Value</key> - <real>8</real> + <real>32</real> </map> <key>RenderTonemapper</key> <map> @@ -12627,27 +12627,16 @@ <key>Value</key> <real>20.0</real> </map> - <key>TextureCameraMotionThreshold</key> + <key>TextureBiasDistanceScale</key> <map> <key>Comment</key> - <string>If the overall motion is lower than this value, textures will be loaded faster</string> + <string>When biasing textures to lower resolution due to lack of vram, weight to put on distance factor.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>F32</string> <key>Value</key> - <real>0.2</real> - </map> - <key>TextureCameraMotionBoost</key> - <map> - <key>Comment</key> - <string>Progressive discard level decrement when the camera is still</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>3</integer> + <real>8.0</real> </map> <key>TextureDecodeDisabled</key> <map> diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl index cf9ce646d1..fe796a054d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl @@ -52,9 +52,6 @@ VARYING vec2 vary_texcoord2; VARYING vec2 vary_texcoord3; VARYING float altitude_blend_factor; -/// Soft clips the light with a gamma correction -vec3 scaleSoftClip(vec3 light); - vec4 cloudNoise(vec2 uv) { vec4 a = texture2D(cloud_noise_texture, uv); @@ -119,7 +116,6 @@ void main() color = (cloudColorSun*(1.-alpha2) + cloudColorAmbient); color.rgb= max(vec3(0), color.rgb); color.rgb *= 2.0; - color.rgb = scaleSoftClip(color.rgb); /// Gamma correct for WL (soft clip effect). frag_data[0] = vec4(color.rgb, alpha1); diff --git a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl index 6ab966ae01..4bf16b50bf 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl @@ -74,7 +74,6 @@ const float ONE_OVER_PI = 0.3183098861; vec3 srgb_to_linear(vec3 cs); vec3 atmosFragLightingLinear(vec3 light, vec3 additive, vec3 atten); -vec3 scaleSoftClipFragLinear(vec3 light); float calcLegacyDistanceAttenuation(float distance, float falloff) { @@ -396,7 +395,7 @@ vec3 pbrIbl(vec3 diffuseColor, specContrib = specular * ao; - return (diffuse + specular*0.5) * ao; //reduce by half to place in appropriate color space for atmospherics + return (diffuse + specular) * ao; } vec3 pbrIbl(vec3 diffuseColor, @@ -562,16 +561,13 @@ vec3 pbrBaseLight(vec3 diffuseColor, vec3 specularColor, float metallic, vec3 v, float NdotV = clamp(abs(dot(norm, v)), 0.001, 1.0); vec3 ibl_spec; - color += pbrIbl(diffuseColor, specularColor, radiance, irradiance, ao, NdotV, 0.2, ibl_spec); + color += pbrIbl(diffuseColor, specularColor, radiance, irradiance, ao, NdotV, perceptualRoughness, ibl_spec); color += pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, norm, v, normalize(light_dir), specContrib) * sunlit * 2.75 * scol; specContrib *= sunlit * 2.75 * scol; specContrib += ibl_spec; - color += colorEmissive*0.5; - - color = atmosFragLightingLinear(color, additive, atten); - color = scaleSoftClipFragLinear(color); + color += colorEmissive; return color; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl b/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl index f0522850de..fb97cd95b4 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl @@ -27,14 +27,9 @@ /*[EXTRA_CODE_HERE]*/ -#ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif vec3 fullbrightAtmosTransport(vec3 light); -vec3 fullbrightScaleSoftClip(vec3 light); VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; @@ -46,8 +41,6 @@ void main() vec4 color = diffuseLookup(vary_texcoord0.xy)*vertex_color; color.rgb = fullbrightAtmosTransport(color.rgb); - color.rgb = fullbrightScaleSoftClip(color.rgb); - frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl index afe504743d..3a15fd1111 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl @@ -88,8 +88,10 @@ void main() #endif #ifndef IS_HUD + color.rgb = fullbrightAtmosTransport(color.rgb); color.rgb = srgb_to_linear(color.rgb); #endif + frag_color.rgb = color.rgb; frag_color.a = color.a; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl index a1cab87092..d41e0b202b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl @@ -59,9 +59,9 @@ ATTRIBUTE vec2 texcoord0; ATTRIBUTE vec4 tangent; ATTRIBUTE vec2 texcoord1; -VARYING vec3 vary_mat0; -VARYING vec3 vary_mat1; -VARYING vec3 vary_mat2; +out vec3 vary_tangent; +flat out float vary_sign; +out vec3 vary_normal; VARYING vec2 vary_texcoord1; #else @@ -111,24 +111,21 @@ void main() vec3 n = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz); #ifdef HAS_NORMAL_MAP vec3 t = normalize((mat*vec4(tangent.xyz+position.xyz,1.0)).xyz-pos.xyz); - vec3 b = cross(n, t)*tangent.w; - - vary_mat0 = vec3(t.x, b.x, n.x); - vary_mat1 = vec3(t.y, b.y, n.y); - vary_mat2 = vec3(t.z, b.z, n.z); + + vary_tangent = t; + vary_sign = tangent.w; + vary_normal = n; #else //HAS_NORMAL_MAP -vary_normal = n; + vary_normal = n; #endif //HAS_NORMAL_MAP #else //HAS_SKIN vec3 n = normalize(normal_matrix * normal); #ifdef HAS_NORMAL_MAP vec3 t = normalize(normal_matrix * tangent.xyz); - vec3 b = cross(n,t)*tangent.w; - //vec3 t = cross(b,n) * binormal.w; - - vary_mat0 = vec3(t.x, b.x, n.x); - vary_mat1 = vec3(t.y, b.y, n.y); - vary_mat2 = vec3(t.z, b.z, n.z); + + vary_tangent = t; + vary_sign = tangent.w; + vary_normal = n; #else //HAS_NORMAL_MAP vary_normal = n; #endif //HAS_NORMAL_MAP diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl index 203c3aca4a..87324bca7f 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl @@ -45,9 +45,6 @@ vec3 linear_to_srgb(vec3 cl); //=============================================================== // tone mapping taken from Khronos sample implementation //=============================================================== -const float GAMMA = 2.2; -const float INV_GAMMA = 1.0 / GAMMA; - // sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT const mat3 ACESInputMat = mat3 @@ -66,29 +63,6 @@ const mat3 ACESOutputMat = mat3 -0.07367, -0.00605, 1.07602 ); - -// linear to sRGB approximation -// see http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html -vec3 linearTosRGB(vec3 color) -{ - return pow(color, vec3(INV_GAMMA)); -} - - -// sRGB to linear approximation -// see http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html -vec3 sRGBToLinear(vec3 srgbIn) -{ - return vec3(pow(srgbIn.xyz, vec3(GAMMA))); -} - - -vec4 sRGBToLinear(vec4 srgbIn) -{ - return vec4(sRGBToLinear(srgbIn.xyz), srgbIn.w); -} - - // ACES tone map (faster approximation) // see: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/ vec3 toneMapACES_Narkowicz(vec3 color) @@ -129,13 +103,13 @@ vec3 toneMapACES_Hill(vec3 color) } uniform float exposure; +uniform float gamma; vec3 toneMap(vec3 color) { color *= exposure; #ifdef TONEMAP_ACES_NARKOWICZ - color *= 0.8; color = toneMapACES_Narkowicz(color); #endif @@ -147,11 +121,12 @@ vec3 toneMap(vec3 color) // boost exposure as discussed in https://github.com/mrdoob/three.js/pull/19621 // this factor is based on the exposure correction of Krzysztof Narkowicz in his // implemetation of ACES tone mapping - color *= 0.85/0.6; + color *= 1.0/0.6; + //color /= 0.6; color = toneMapACES_Hill(color); #endif - return linearTosRGB(color); + return linear_to_srgb(color); } //=============================================================== @@ -194,16 +169,26 @@ float noise(vec2 x) { //============================= + +vec3 legacyGamma(vec3 color) +{ + color = 1. - clamp(color, vec3(0.), vec3(1.)); + color = 1. - pow(color, vec3(gamma)); // s/b inverted already CPU-side + + return color; +} + void main() { //this is the one of the rare spots where diffuseRect contains linear color values (not sRGB) vec4 diff = texture2D(diffuseRect, vary_fragcoord) + texture2D(emissiveRect, vary_fragcoord); diff.rgb = toneMap(diff.rgb); - vec2 tc = vary_fragcoord.xy*screen_res; - + diff.rgb = legacyGamma(diff.rgb); + + vec2 tc = vary_fragcoord.xy*screen_res*4.0; vec3 seed = (diff.rgb+vec3(1.0))*vec3(tc.xy, tc.x+tc.y); vec3 nz = vec3(noise(seed.rg), noise(seed.gb), noise(seed.rb)); - diff.rgb += nz*0.008; + diff.rgb += nz*0.003; //diff.rgb = nz; frag_color = diff; } diff --git a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl index 16651dcdbc..745999fc2f 100644 --- a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl @@ -33,6 +33,7 @@ uniform float waterFogKS; vec3 getPositionEye(); vec3 srgb_to_linear(vec3 col); +vec3 linear_to_srgb(vec3 col); vec4 applyWaterFogView(vec3 pos, vec4 color) { @@ -68,48 +69,16 @@ vec4 applyWaterFogView(vec3 pos, vec4 color) float D = pow(0.98, l*kd); color.rgb = color.rgb * D + kc.rgb * L; + color.a = kc.a + color.a; return color; } vec4 applyWaterFogViewLinearNoClip(vec3 pos, vec4 color, vec3 sunlit) { - vec3 view = normalize(pos); - //normalize view vector - float es = -(dot(view, waterPlane.xyz)); - - - //find intersection point with water plane and eye vector - - //get eye depth - float e0 = max(-waterPlane.w, 0.0); - - vec3 int_v = waterPlane.w > 0.0 ? view * waterPlane.w / es : vec3(0.0, 0.0, 0.0); - - //get object depth - float depth = length(pos - int_v); - - //get "thickness" of water - float l = max(depth, 0.1); - - float kd = waterFogDensity*1.3; - float ks = waterFogKS; - vec4 kc = waterFogColor; - kc.rgb = srgb_to_linear(kc.rgb); // TODO -- pass in waterFogColor linear - kc.rgb *= sunlit; - - float F = 0.98; - - float t1 = -kd * pow(F, ks * e0); - float t2 = kd + ks * es; - float t3 = pow(F, t2 * l) - 1.0; - - float L = min(t1 / t2 * t3, 1.0); - - float D = pow(0.98, l * kd); - - color.rgb = color.rgb * D + kc.rgb * L; - + color.rgb = linear_to_srgb(color.rgb); + color = applyWaterFogView(pos, color); + color.rgb = srgb_to_linear(color.rgb); return color; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index e2694e060e..ef35bf3fd7 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -250,6 +250,9 @@ void main() calcAtmosphericVarsLinear(pos.xyz, norm, light_dir, sunlit, amblit, additive, atten); + vec3 sunlit_linear = srgb_to_linear(sunlit); + vec3 amblit_linear = amblit; + vec3 irradiance; vec3 glossenv; vec3 legacyenv; @@ -266,7 +269,7 @@ void main() color.a = final_alpha; - vec3 sun_contrib = min(final_da, shadow) * sunlit; + vec3 sun_contrib = min(final_da, shadow) * sunlit_linear; color.rgb = max(amblit, irradiance); @@ -274,8 +277,10 @@ void main() color.rgb *= diffuse_linear.rgb; + color.rgb = linear_to_srgb(color.rgb); color.rgb = atmosFragLightingLinear(color.rgb, additive, atten); color.rgb = scaleSoftClipFragLinear(color.rgb); + color.rgb = srgb_to_linear(color.rgb); vec4 light = vec4(0,0,0,0); @@ -294,8 +299,9 @@ void main() color.rgb += light.rgb; #endif // !defined(LOCAL_LIGHT_KILL) + #ifdef WATER_FOG - color = applyWaterFogViewLinear(pos.xyz, color, sunlit); + color = applyWaterFogViewLinear(pos.xyz, color, sunlit_linear); #endif // WATER_FOG #endif // #else // FOR_IMPOSTOR @@ -303,6 +309,7 @@ void main() #ifdef IS_HUD color.rgb = linear_to_srgb(color.rgb); #endif + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl index 2a093827cb..fb76db99a0 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl @@ -82,6 +82,8 @@ vec3 srgb_to_linear(vec3 c); vec3 linear_to_srgb(vec3 c); void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive); +vec3 atmosFragLightingLinear(vec3 color, vec3 additive, vec3 atten); +vec3 scaleSoftClipFragLinear(vec3 color); void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist); float calcLegacyDistanceAttenuation(float distance, float falloff); @@ -196,6 +198,8 @@ void main() vec3 atten; calcAtmosphericVarsLinear(pos.xyz, norm, light_dir, sunlit, amblit, additive, atten); + vec3 sunlit_linear = srgb_to_linear(sunlit); + vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; #ifdef HAS_SUN_SHADOW @@ -229,9 +233,14 @@ void main() vec3 v = -normalize(pos.xyz); vec3 spec; - color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit, scol, radiance, irradiance, colorEmissive, ao, additive, atten, spec); + color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten, spec); glare += max(max(spec.r, spec.g), spec.b); + color.rgb = linear_to_srgb(color.rgb); + color.rgb = atmosFragLightingLinear(color.rgb, additive, atten); + color.rgb = scaleSoftClipFragLinear(color.rgb); + color.rgb = srgb_to_linear(color.rgb); + vec3 light = vec3(0); // Punctual lights diff --git a/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl index 5fa53c374b..080f622155 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl @@ -47,7 +47,6 @@ void sampleReflectionProbesWater(inout vec3 ambenv, inout vec3 glossenv, vec2 tc, vec3 pos, vec3 norm, float glossiness) { sampleReflectionProbes(ambenv, glossenv, tc, pos, norm, glossiness); - glossenv *= 8.0; } vec4 sampleReflectionProbesDebug(vec3 pos) diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl index 6668a00841..1d02498209 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl @@ -33,8 +33,8 @@ vec3 linear_to_srgb(vec3 col); vec3 atmosFragLighting(vec3 light, vec3 additive, vec3 atten) { light *= atten.r; - light += additive; - return light * 2.0; + light += additive * 2.0; + return light; } vec3 atmosFragLightingLinear(vec3 light, vec3 additive, vec3 atten) diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl index f9f625ecdb..55e1411be2 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl @@ -137,12 +137,15 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou additive = (blue_horizon.rgb * blue_weight.rgb) * (cs + tmpAmbient.rgb) + (haze_horizon * haze_weight.rgb) * (cs * haze_glow + tmpAmbient.rgb); // brightness of surface both sunlight and ambient - sunlit = sunlight.rgb; - amblit = tmpAmbient.rgb; + + // fudge sunlit and amblit to get consistent lighting compared to legacy + // midday before PBR was a thing + sunlit = sunlight.rgb * 0.7; + amblit = tmpAmbient.rgb * 0.25; + additive *= vec3(1.0 - combined_haze); } - vec3 srgb_to_linear(vec3 col); // provide a touch of lighting in the opposite direction of the sun light @@ -150,21 +153,26 @@ vec3 srgb_to_linear(vec3 col); float ambientLighting(vec3 norm, vec3 light_dir) { float ambient = min(abs(dot(norm.xyz, light_dir.xyz)), 1.0); - ambient *= 0.56; + ambient *= 0.5; ambient *= ambient; ambient = (1.0 - ambient); return ambient; } -// return colors in linear space +// return lit amblit in linear space, leave sunlit and additive in sRGB space void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten) { calcAtmosphericVars(inPositionEye, light_dir, 1.0, sunlit, amblit, additive, atten, false); - sunlit = srgb_to_linear(sunlit); - additive = srgb_to_linear(additive); - amblit = ambient_linear; + + // multiply by 2 to get same colors as when the "scaleSoftClip" implementation was doubling color values + // (allows for mixing of light sources other than sunlight e.g. reflection probes) + sunlit *= 2.0; + + // squash ambient to approximate whatever weirdness legacy atmospherics were doing + amblit = ambient_color * 0.5; amblit *= ambientLighting(norm, light_dir); + amblit = srgb_to_linear(amblit); } diff --git a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl index 9a9b179e6a..027bfb866f 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl @@ -22,43 +22,34 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ -uniform float gamma; -vec3 getAtmosAttenuation(); -vec3 getAdditiveColor(); + // DEPRECATED -vec3 srgb_to_linear(vec3 col); -vec3 linear_to_srgb(vec3 col); +//soft clip effect has been moved to postDeferredGammaCorrect legacyGamma, this file is effectively dead +// but these functions need to be removed from all existing shaders before removing this file -vec3 scaleSoftClipFragLinear(vec3 light) -{ // identical to non-linear version and that's probably close enough - //soft clip effect: - light = 1. - clamp(light, vec3(0.), vec3(1.)); - light = 1. - pow(light, vec3(gamma)); // s/b inverted already CPU-side +vec3 scaleSoftClipFrag(vec3 light) +{ return light; } -vec3 scaleSoftClipFrag(vec3 light) -{ - //soft clip effect: - light = 1. - clamp(light, vec3(0.), vec3(1.)); - light = 1. - pow(light, vec3(gamma)); // s/b inverted already CPU-side +vec3 scaleSoftClipFragLinear(vec3 light) +{ // identical to non-linear version and that's probably close enough return light; } vec3 scaleSoftClip(vec3 light) { - return scaleSoftClipFrag(light); + return light; } vec3 fullbrightScaleSoftClipFrag(vec3 light, vec3 add, vec3 atten) { - //return mix(scaleSoftClipFrag(light.rgb), add, atten); - return scaleSoftClipFrag(light.rgb); + return light; } vec3 fullbrightScaleSoftClip(vec3 light) { - return fullbrightScaleSoftClipFrag(light, getAdditiveColor(), getAtmosAttenuation()); + return light; } diff --git a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl index c509d865ba..6aa719d200 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl @@ -48,23 +48,27 @@ vec3 atmosTransport(vec3 light) vec3 fullbrightAtmosTransportFragLinear(vec3 light, vec3 additive, vec3 atten) { // same as non-linear version, probably fine - float brightness = dot(light.rgb * 0.5, vec3(0.3333)) + 0.1; - return mix(atmosTransportFrag(light.rgb, additive, atten), light.rgb + additive, brightness * brightness); + //float brightness = dot(light.rgb * 0.5, vec3(0.3333)) + 0.1; + //return mix(atmosTransportFrag(light.rgb, additive, atten), light.rgb + additive, brightness * brightness); + return atmosTransportFrag(light, additive, atten); } vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten) { - float brightness = dot(light.rgb * 0.5, vec3(0.3333)) + 0.1; - return mix(atmosTransportFrag(light.rgb, additive, atten), light.rgb + additive, brightness * brightness); + //float brightness = dot(light.rgb * 0.5, vec3(0.3333)) + 0.1; + //return mix(atmosTransportFrag(light.rgb, additive, atten), light.rgb + additive, brightness * brightness); + return atmosTransportFrag(light, additive, atten); } vec3 fullbrightAtmosTransport(vec3 light) { - return fullbrightAtmosTransportFrag(light, getAdditiveColor(), getAtmosAttenuation()); + //return fullbrightAtmosTransportFrag(light, getAdditiveColor(), getAtmosAttenuation()); + return atmosTransport(light); } vec3 fullbrightShinyAtmosTransport(vec3 light) { - float brightness = dot(light.rgb, vec3(0.33333)); - return mix(atmosTransport(light.rgb), (light.rgb + getAdditiveColor().rgb) * (2.0 - brightness), brightness * brightness); + //float brightness = dot(light.rgb, vec3(0.33333)); + //return mix(atmosTransport(light.rgb), (light.rgb + getAdditiveColor().rgb) * (2.0 - brightness), brightness * brightness); + return atmosTransport(light); } diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl index 49529860be..6e41df34a4 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl @@ -210,9 +210,9 @@ uniform float minimum_alpha; #endif #ifdef HAS_NORMAL_MAP -VARYING vec3 vary_mat0; -VARYING vec3 vary_mat1; -VARYING vec3 vary_mat2; +in vec3 vary_normal; +in vec3 vary_tangent; +flat in float vary_sign; VARYING vec2 vary_texcoord1; #else VARYING vec3 vary_normal; @@ -227,14 +227,17 @@ vec2 encode_normal(vec3 n); vec3 getNormal(inout float glossiness) { #ifdef HAS_NORMAL_MAP - vec4 norm = texture2D(bumpMap, vary_texcoord1.xy); - glossiness *= norm.a; - - norm.xyz = norm.xyz * 2 - 1; + vec4 vNt = texture2D(bumpMap, vary_texcoord1.xy); + glossiness *= vNt.a; + vNt.xyz = vNt.xyz * 2 - 1; + float sign = vary_sign; + vec3 vN = vary_normal; + vec3 vT = vary_tangent.xyz; + + vec3 vB = sign * cross(vN, vT); + vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN ); - return normalize(vec3(dot(norm.xyz,vary_mat0), - dot(norm.xyz,vary_mat1), - dot(norm.xyz,vary_mat2))); + return tnorm; #else return normalize(vary_normal); #endif @@ -316,6 +319,7 @@ void main() //forward rendering, output lit linear color diffcol.rgb = srgb_to_linear(diffcol.rgb); spec.rgb = srgb_to_linear(spec.rgb); + spec.a = glossiness; // pack glossiness into spec alpha for lighting functions vec3 pos = vary_position; @@ -334,16 +338,19 @@ void main() vec3 atten; calcAtmosphericVarsLinear(pos.xyz, norm.xyz, light_dir, sunlit, amblit, additive, atten); + vec3 sunlit_linear = srgb_to_linear(sunlit); + vec3 amblit_linear = amblit; + vec3 ambenv; vec3 glossenv; vec3 legacyenv; sampleReflectionProbesLegacy(ambenv, glossenv, legacyenv, pos.xy*0.5+0.5, pos.xyz, norm.xyz, glossiness, env); // use sky settings ambient or irradiance map sample, whichever is brighter - color = max(amblit, ambenv); + color = max(amblit_linear, ambenv); float da = clamp(dot(norm.xyz, light_dir.xyz), 0.0, 1.0); - vec3 sun_contrib = min(da, shadow) * sunlit; + vec3 sun_contrib = min(da, shadow) * sunlit_linear; color.rgb += sun_contrib; color *= diffcol.rgb; @@ -354,7 +361,7 @@ void main() if (glossiness > 0.0) // specular reflection { float sa = dot(normalize(refnormpersp), light_dir.xyz); - vec3 dumbshiny = sunlit * shadow * (texture2D(lightFunc, vec2(sa, glossiness)).r); + vec3 dumbshiny = sunlit_linear * shadow * (texture2D(lightFunc, vec2(sa, glossiness)).r); // add the two types of shiny together vec3 spec_contrib = dumbshiny * spec.rgb; @@ -379,8 +386,10 @@ void main() glare += cur_glare; } - color.rgb = mix(atmosFragLightingLinear(color.rgb, additive, atten), fullbrightAtmosTransportFragLinear(color, additive, atten), emissive); + color.rgb = linear_to_srgb(color.rgb); + color.rgb = atmosFragLightingLinear(color.rgb, additive, atten); color.rgb = scaleSoftClipFragLinear(color.rgb); + color.rgb = srgb_to_linear(color.rgb); vec3 npos = normalize(-pos.xyz); vec3 light = vec3(0, 0, 0); diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 23c6f4d5ae..a6a2543915 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -458,28 +458,24 @@ float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, float min_da, int i // dir - pixel normal // w - weight of sample (distance and angular attenuation) // dw - weight of sample (distance only) -// vi - return value of intersection point with influence volume -// wi - return value of approximate world space position of sampled pixel -// lod - which mip to bias towards (lower is higher res, sharper reflections) +// lod - which mip to sample (lower is higher res, sharper reflections) // c - center of probe // r2 - radius of probe squared // i - index of probe -vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, out vec3 vi, out vec3 wi, float lod, vec3 c, int i) +vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c, int i) { - //lod = max(lod, 1); // parallax adjustment - vec3 v; if (refIndex[i].w < 0) - { + { // box probe float d = 0; v = boxIntersect(pos, dir, i, d); w = max(d, 0.001); } else - { + { // sphere probe float r = refSphere[i].w; float rr = r * r; @@ -491,16 +487,12 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, out vec3 vi, out v w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.25, i, dw); } - vi = v; - v -= c; vec3 d = normalize(v); v = env_mat * v; - vec4 ret = textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod); - - wi = d * ret.a * 256.0+c; + vec4 ret = textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod) * refParams[i].y; return ret.rgb; } @@ -568,12 +560,11 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod) float w = 0; float dw = 0; - vec3 vi, wi; vec3 refcol; { - refcol = tapRefMap(pos, dir, w, dw, vi, wi, lod, refSphere[i].xyz, i); + refcol = tapRefMap(pos, dir, w, dw, lod, refSphere[i].xyz, i); col[p] += refcol.rgb*w; wsum[p] += w; @@ -665,7 +656,7 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, vec2 tc, vec3 pos, vec3 norm, float glossiness) { // TODO - don't hard code lods - float reflection_lods = max_probe_lod; + float reflection_lods = max_probe_lod-1; preProbeSample(pos); vec3 refnormpersp = reflect(pos.xyz, norm.xyz); @@ -690,6 +681,9 @@ void sampleReflectionProbesWater(inout vec3 ambenv, inout vec3 glossenv, vec2 tc, vec3 pos, vec3 norm, float glossiness) { sampleReflectionProbes(ambenv, glossenv, tc, pos, norm, glossiness); + + // fudge factor to get PBR water at a similar luminance ot legacy water + glossenv *= 0.25; } void debugTapRefMap(vec3 pos, vec3 dir, float depth, int i, inout vec4 col) diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 8d48e6f596..dfd1d47b3e 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -85,6 +85,8 @@ float getDepth(vec2 pos_screen); vec3 linear_to_srgb(vec3 c); vec3 srgb_to_linear(vec3 c); +uniform vec4 waterPlane; + #ifdef WATER_FOG vec4 applyWaterFogViewLinear(vec3 pos, vec4 color); #endif @@ -153,6 +155,24 @@ void main() calcAtmosphericVarsLinear(pos.xyz, norm.xyz, light_dir, sunlit, amblit, additive, atten); + vec3 sunlit_linear = srgb_to_linear(sunlit); + vec3 amblit_linear = amblit; + + bool do_atmospherics = false; + +#ifndef WATER_FOG + // when above water, mask off atmospherics below water + if (dot(pos.xyz, waterPlane.xyz) + waterPlane.w > 0.0) + { + do_atmospherics = true; + } +#else + do_atmospherics = true; +#endif + + vec3 irradiance = vec3(0); + vec3 radiance = vec3(0); + if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR)) { vec3 orm = texture2D(specularRect, tc).rgb; @@ -161,23 +181,32 @@ void main() float ao = orm.r * ambocc; vec3 colorEmissive = texture2D(emissiveRect, tc).rgb; - // PBR IBL float gloss = 1.0 - perceptualRoughness; - vec3 irradiance = vec3(0); - vec3 radiance = vec3(0); + sampleReflectionProbes(irradiance, radiance, tc, pos.xyz, norm.xyz, gloss); // Take maximium of legacy ambient vs irradiance sample as irradiance // NOTE: ao is applied in pbrIbl (see pbrBaseLight), do not apply here - irradiance = max(amblit,irradiance); + irradiance = max(amblit_linear,irradiance); vec3 diffuseColor; vec3 specularColor; calcDiffuseSpecular(baseColor.rgb, metallic, diffuseColor, specularColor); vec3 v = -normalize(pos.xyz); - color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit, scol, radiance, irradiance, colorEmissive, ao, additive, atten); + color = vec3(1,0,1); + color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten); + + + if (do_atmospherics) + { + color = linear_to_srgb(color); + color = atmosFragLightingLinear(color, additive, atten); + color = srgb_to_linear(color); + } + + } else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS)) { @@ -199,12 +228,12 @@ void main() sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, tc, pos.xyz, norm.xyz, spec.a, envIntensity); // use sky settings ambient or irradiance map sample, whichever is brighter - irradiance = max(amblit, irradiance); + irradiance = max(amblit_linear, irradiance); // apply lambertian IBL only (see pbrIbl) color.rgb = irradiance * ambocc; - vec3 sun_contrib = min(da, scol) * sunlit; + vec3 sun_contrib = min(da, scol) * sunlit_linear; color.rgb += sun_contrib; color.rgb *= baseColor.rgb; @@ -230,9 +259,16 @@ void main() applyLegacyEnv(color, legacyenv, spec, pos.xyz, norm.xyz, envIntensity); } - color = mix(atmosFragLightingLinear(color, additive, atten), fullbrightAtmosTransportFragLinear(color, additive, atten), baseColor.a); - color = scaleSoftClipFragLinear(color); - } + + if (do_atmospherics) + { + color = linear_to_srgb(color); + color = atmosFragLightingLinear(color, additive, atten); + color = srgb_to_linear(color); + } + } + + #ifdef WATER_FOG vec4 fogged = applyWaterFogViewLinear(pos.xyz, vec4(color, bloom)); diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl index a87682affb..7524567f6b 100644 --- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl @@ -114,6 +114,7 @@ vec3 BlendNormal(vec3 bump1, vec3 bump2) } vec3 srgb_to_linear(vec3 col); +vec3 linear_to_srgb(vec3 col); vec3 vN, vT, vB; @@ -200,6 +201,8 @@ void main() calcAtmosphericVarsLinear(pos.xyz, wavef, vary_light_dir, sunlit, amblit, additive, atten); + vec3 sunlit_linear = srgb_to_linear(sunlit); + #ifdef TRANSPARENT_WATER vec4 fb = texture2D(screenTex, distort2); float depth = texture2D(screenDepth, distort2).r; @@ -216,9 +219,12 @@ void main() fb = applyWaterFogViewLinear(refPos, fb, sunlit); #else - vec4 fb = applyWaterFogViewLinear(viewVec*2048.0, vec4(1.0), sunlit); + vec4 fb = applyWaterFogViewLinear(viewVec*2048.0, vec4(1.0), sunlit_linear); #endif + // fudge sample on other side of water to be a tad darker + fb.rgb *= 0.75; + float metallic = 0.0; float perceptualRoughness = 0.05; float gloss = 1.0 - perceptualRoughness; @@ -247,10 +253,7 @@ void main() vec3 punctual = pbrPunctual(vec3(0), specularColor, 0.1, metallic, normalize(wavef+up*max(dist, 32.0)/32.0*(1.0-vdu)), v, normalize(light_dir)); - vec3 color = punctual * sunlit * 2.75 * scol; - - color = atmosFragLightingLinear(color, additive, atten); - color = scaleSoftClipFragLinear(color); + vec3 color = punctual * sunlit_linear * 2.75 * scol; vec3 ibl = pbrIbl(vec3(0), vec3(1), radiance, vec3(0), ao, NdotV, 0.0); @@ -274,6 +277,12 @@ void main() color = mix(color, fb.rgb, f); + color.rgb = linear_to_srgb(color.rgb); + color = atmosFragLightingLinear(color, additive, atten); + color = scaleSoftClipFragLinear(color); + color.rgb = srgb_to_linear(color.rgb); + + float spec = min(max(max(punctual.r, punctual.g), punctual.b), 0.05); frag_color = vec4(color, spec); //*sunAngle2); diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index b24244c188..020c7bbc74 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -1,4 +1,4 @@ -version 50 +version 51 // 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 @@ -99,7 +99,7 @@ RenderVolumeLODFactor 1 1.125 RenderDeferredSSAO 1 0 RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 0 -WLSkyDetail 1 48 +WLSkyDetail 1 96 RenderFSAASamples 1 0 RenderScreenSpaceReflections 1 0 @@ -126,7 +126,7 @@ RenderVolumeLODFactor 1 1.125 RenderDeferredSSAO 1 0 RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 0 -WLSkyDetail 1 48 +WLSkyDetail 1 96 RenderFSAASamples 1 0 RenderScreenSpaceReflections 1 0 @@ -151,7 +151,7 @@ RenderVolumeLODFactor 1 1.125 RenderDeferredSSAO 1 0 RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 0 -WLSkyDetail 1 48 +WLSkyDetail 1 96 RenderFSAASamples 1 2 RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 0 @@ -178,7 +178,7 @@ RenderVolumeLODFactor 1 1.125 RenderDeferredSSAO 1 0 RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 0 -WLSkyDetail 1 48 +WLSkyDetail 1 96 RenderFSAASamples 1 2 RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 @@ -205,7 +205,7 @@ RenderVolumeLODFactor 1 1.125 RenderDeferredSSAO 1 1 RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 0 -WLSkyDetail 1 48 +WLSkyDetail 1 96 RenderFSAASamples 1 2 RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 @@ -232,7 +232,7 @@ RenderVolumeLODFactor 1 1.125 RenderDeferredSSAO 1 1 RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 2 -WLSkyDetail 1 48 +WLSkyDetail 1 96 RenderFSAASamples 1 2 RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index df12f56dd2..dbb33b3997 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -1,4 +1,4 @@ -version 45 +version 46 // 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 @@ -95,7 +95,7 @@ RenderVolumeLODFactor 1 0.5 RenderDeferredSSAO 1 0 RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 0 -WLSkyDetail 1 48 +WLSkyDetail 1 96 RenderFSAASamples 1 0 RenderReflectionsEnabled 1 0 RenderReflectionProbeDetail 1 0 @@ -122,7 +122,7 @@ RenderVolumeLODFactor 1 1.125 RenderDeferredSSAO 1 0 RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 0 -WLSkyDetail 1 48 +WLSkyDetail 1 96 RenderFSAASamples 1 0 RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 0 @@ -149,7 +149,7 @@ RenderVolumeLODFactor 1 1.125 RenderDeferredSSAO 1 0 RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 0 -WLSkyDetail 1 48 +WLSkyDetail 1 96 RenderFSAASamples 1 2 RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 0 @@ -176,7 +176,7 @@ RenderVolumeLODFactor 1 1.125 RenderDeferredSSAO 1 0 RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 0 -WLSkyDetail 1 48 +WLSkyDetail 1 96 RenderFSAASamples 1 2 RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 0 @@ -203,7 +203,7 @@ RenderVolumeLODFactor 1 1.125 RenderDeferredSSAO 1 1 RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 0 -WLSkyDetail 1 48 +WLSkyDetail 1 96 RenderFSAASamples 1 2 RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 @@ -230,7 +230,7 @@ RenderVolumeLODFactor 1 1.125 RenderDeferredSSAO 1 1 RenderShadowDetail 1 2 RenderUseAdvancedAtmospherics 1 0 -WLSkyDetail 1 48 +WLSkyDetail 1 96 RenderFSAASamples 1 2 RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 061feba0a4..7731f37c94 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -572,8 +572,7 @@ static void settings_to_globals() static void settings_modify() { LLPipeline::sRenderTransparentWater = gSavedSettings.getBOOL("RenderTransparentWater"); - LLPipeline::sRenderBump = TRUE; // FALSE is deprecated -- gSavedSettings.getBOOL("RenderObjectBump"); - LLPipeline::sRenderDeferred = TRUE; // FALSE is deprecated -- LLPipeline::sRenderBump&& gSavedSettings.getBOOL("RenderDeferred"); + LLPipeline::sRenderDeferred = TRUE; // FALSE is deprecated LLRenderTarget::sUseFBO = LLPipeline::sRenderDeferred; LLVOSurfacePatch::sLODFactor = gSavedSettings.getF32("RenderTerrainLODFactor"); LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4] diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 45df4d0eee..04b6ebd14c 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -1094,11 +1094,11 @@ void LLDrawable::updateUVMinMax() bool LLDrawable::isVisible() const { if (LLViewerOctreeEntryData::isVisible()) -{ - return true; -} + { + return true; + } -{ + { LLViewerOctreeGroup* group = mEntry->getGroup(); if (group && group->isVisible()) { diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index a74950dad2..d7e4632ab0 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -357,8 +357,6 @@ void LLFace::switchTexture(U32 ch, LLViewerTexture* new_texture) llassert(mTexture[ch].notNull()); - new_texture->addTextureStats(mTexture[ch]->getMaxVirtualSize()) ; - if (ch == LLRender::DIFFUSE_MAP) { getViewerObject()->changeTEImage(mTEOffset, new_texture) ; @@ -1109,20 +1107,13 @@ bool LLFace::canRenderAsMask() (te->getGlow() == 0.f) && // glowing masks are hard to implement - don't mask getTexture()->getIsAlphaMask()) // texture actually qualifies for masking (lazily recalculated but expensive) { - if (LLPipeline::sRenderDeferred) - { - if (getViewerObject()->isHUDAttachment() || te->getFullbright()) - { //hud attachments and fullbright objects are NOT subject to the deferred rendering pipe - return LLPipeline::sAutoMaskAlphaNonDeferred; - } - else - { - return LLPipeline::sAutoMaskAlphaDeferred; - } + if (getViewerObject()->isHUDAttachment() || te->getFullbright()) + { //hud attachments and fullbright objects are NOT subject to the deferred rendering pipe + return LLPipeline::sAutoMaskAlphaNonDeferred; } else { - return LLPipeline::sAutoMaskAlphaNonDeferred; + return LLPipeline::sAutoMaskAlphaDeferred; } } @@ -1262,19 +1253,10 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, bool shiny_in_alpha = false; - if (LLPipeline::sRenderDeferred) - { //store shiny in alpha if we don't have a specular map - if (!mat || mat->getSpecularID().isNull()) - { - shiny_in_alpha = true; - } - } - else + //store shiny in alpha if we don't have a specular map + if (!mat || mat->getSpecularID().isNull()) { - if (!mat || mat->getDiffuseAlphaMode() != LLMaterial::DIFFUSE_ALPHA_MODE_MASK) - { - shiny_in_alpha = true; - } + shiny_in_alpha = true; } if (shiny_in_alpha) @@ -1322,39 +1304,75 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } } + + LLMaterial* mat = tep->getMaterialParams().get(); + LLGLTFMaterial* gltf_mat = tep->getGLTFRenderMaterial(); + F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0; - bool do_xform = false; - if (rebuild_tcoord) - { - if (tep) - { - r = tep->getRotation(); - os = tep->mOffsetS; - ot = tep->mOffsetT; - ms = tep->mScaleS; - mt = tep->mScaleT; - cos_ang = cos(r); - sin_ang = sin(r); - - if (cos_ang != 1.f || - sin_ang != 0.f || - os != 0.f || - ot != 0.f || - ms != 1.f || - mt != 1.f) - { - do_xform = true; - } - else - { - do_xform = false; - } - } - else - { - do_xform = false; - } - } + + constexpr S32 XFORM_NONE = 0; + constexpr S32 XFORM_BLINNPHONG_COLOR = 1; + constexpr S32 XFORM_BLINNPHONG_NORMAL = 1 << 1; + constexpr S32 XFORM_BLINNPHONG_SPECULAR = 1 << 2; + + S32 xforms = XFORM_NONE; + // For GLTF, transforms will be applied later + if (rebuild_tcoord && tep && !gltf_mat) + { + r = tep->getRotation(); + os = tep->mOffsetS; + ot = tep->mOffsetT; + ms = tep->mScaleS; + mt = tep->mScaleT; + cos_ang = cos(r); + sin_ang = sin(r); + + if (cos_ang != 1.f || + sin_ang != 0.f || + os != 0.f || + ot != 0.f || + ms != 1.f || + mt != 1.f) + { + xforms |= XFORM_BLINNPHONG_COLOR; + } + if (mat) + { + F32 r_norm = 0, os_norm = 0, ot_norm = 0, ms_norm = 0, mt_norm = 0, cos_ang_norm = 0, sin_ang_norm = 0; + mat->getNormalOffset(os_norm, ot_norm); + mat->getNormalRepeat(ms_norm, mt_norm); + r_norm = mat->getNormalRotation(); + cos_ang_norm = cos(r_norm); + sin_ang_norm = sin(r_norm); + if (cos_ang_norm != 1.f || + sin_ang_norm != 0.f || + os_norm != 0.f || + ot_norm != 0.f || + ms_norm != 1.f || + mt_norm != 1.f) + { + xforms |= XFORM_BLINNPHONG_NORMAL; + } + } + if (mat) + { + F32 r_spec = 0, os_spec = 0, ot_spec = 0, ms_spec = 0, mt_spec = 0, cos_ang_spec = 0, sin_ang_spec = 0; + mat->getSpecularOffset(os_spec, ot_spec); + mat->getSpecularRepeat(ms_spec, mt_spec); + r_spec = mat->getSpecularRotation(); + cos_ang_spec = cos(r_spec); + sin_ang_spec = sin(r_spec); + if (cos_ang_spec != 1.f || + sin_ang_spec != 0.f || + os_spec != 0.f || + ot_spec != 0.f || + ms_spec != 1.f || + mt_spec != 1.f) + { + xforms |= XFORM_BLINNPHONG_SPECULAR; + } + } + } const LLMeshSkinInfo* skin = nullptr; LLMatrix4a mat_vert; @@ -1495,7 +1513,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, sin_ang = 0.f; ms = mt = 1.f; - do_xform = false; + xforms = XFORM_NONE; } if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) // || isState(LLFace::RIGGED)) @@ -1507,15 +1525,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLVector4a scalea; scalea.load3(scale.mV); - LLMaterial* mat = tep->getMaterialParams().get(); - LLGLTFMaterial* gltf_mat = tep->getGLTFRenderMaterial(); - - if (gltf_mat) - { - // Transforms will be applied later - do_xform = false; - } - bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); if ((mat || gltf_mat) && !do_bump) @@ -1524,7 +1533,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, || mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD2); } - bool do_tex_mat = tex_mode && mTextureMatrix; + // For GLTF materials: Transforms will be applied later + bool do_tex_mat = tex_mode && mTextureMatrix && !gltf_mat; if (!do_bump) { //not bump mapped, might be able to do a cheap update @@ -1535,7 +1545,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - texgen"); if (!do_tex_mat) { - if (!do_xform) + if (xforms == XFORM_NONE) { LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("ggv - texgen 1"); S32 tc_size = (num_vertices*2*sizeof(F32)+0xF) & ~0xF; @@ -1614,7 +1624,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, *tex_coords0++ = tc; } } - else + else if (xforms != XFORM_NONE) { for (S32 i = 0; i < num_vertices; i++) { @@ -1630,6 +1640,20 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, *tex_coords0++ = tc; } } + else + { + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); + LLVector4a& norm = vf.mNormals[i]; + LLVector4a& center = *(vf.mCenter); + LLVector4a vec = vf.mPositions[i]; + vec.mul(scalea); + planarProjection(tc, norm, center, vec); + + *tex_coords0++ = tc; + } + } } } else @@ -1647,12 +1671,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, for (U32 ch = 0; ch < 3; ++ch) { + S32 xform_channel = XFORM_NONE; switch (ch) { case 0: + xform_channel = XFORM_BLINNPHONG_COLOR; mVertexBuffer->getTexCoord0Strider(dst, mGeomIndex, mGeomCount); break; case 1: + xform_channel = XFORM_BLINNPHONG_NORMAL; if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)) { mVertexBuffer->getTexCoord1Strider(dst, mGeomIndex, mGeomCount); @@ -1673,6 +1700,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } break; case 2: + xform_channel = XFORM_BLINNPHONG_SPECULAR; if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD2)) { mVertexBuffer->getTexCoord2Strider(dst, mGeomIndex, mGeomCount); @@ -1692,46 +1720,47 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } break; } + const bool do_xform = (xforms & xform_channel) != XFORM_NONE; - for (S32 i = 0; i < num_vertices; i++) - { - LLVector2 tc(vf.mTexCoords[i]); - - LLVector4a& norm = vf.mNormals[i]; - - LLVector4a& center = *(vf.mCenter); - - if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) - { - LLVector4a vec = vf.mPositions[i]; - - vec.mul(scalea); - - if (texgen == LLTextureEntry::TEX_GEN_PLANAR) - { - planarProjection(tc, norm, center, vec); - } - } - - if (tex_mode && mTextureMatrix) - { - LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); - tmp = tmp * *mTextureMatrix; - tc.mV[0] = tmp.mV[0]; - tc.mV[1] = tmp.mV[1]; - } - else - { - xform(tc, cos_ang, sin_ang, os, ot, ms, mt); - } - - *dst++ = tc; - if (do_bump) - { - bump_tc.push_back(tc); - } - } + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); + + LLVector4a& norm = vf.mNormals[i]; + + LLVector4a& center = *(vf.mCenter); + + if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) + { + LLVector4a vec = vf.mPositions[i]; + + vec.mul(scalea); + + if (texgen == LLTextureEntry::TEX_GEN_PLANAR) + { + planarProjection(tc, norm, center, vec); + } + } + + if (tex_mode && mTextureMatrix) + { + LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); + tmp = tmp * *mTextureMatrix; + tc.mV[0] = tmp.mV[0]; + tc.mV[1] = tmp.mV[1]; + } + else if (do_xform) + { + xform(tc, cos_ang, sin_ang, os, ot, ms, mt); + } + + *dst++ = tc; + if (do_bump) + { + bump_tc.push_back(tc); + } + } } if ((!mat && !gltf_mat) && do_bump) diff --git a/indra/newview/llface.h b/indra/newview/llface.h index ee8316018b..0a66dc6ba6 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -235,6 +235,7 @@ public: //aligned members LLVector4a mExtents[2]; private: + friend class LLViewerTextureList; F32 adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius ); BOOL calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) ; public: diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 29e8210d8e..014c8a4d2d 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -631,6 +631,7 @@ std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadF allowedv->push_back("anim"); break; case FFLOAD_GLTF: + case FFLOAD_MATERIAL: allowedv->push_back("gltf"); allowedv->push_back("glb"); break; diff --git a/indra/newview/lllocalgltfmaterials.cpp b/indra/newview/lllocalgltfmaterials.cpp index a9099b1ce9..996b168262 100644 --- a/indra/newview/lllocalgltfmaterials.cpp +++ b/indra/newview/lllocalgltfmaterials.cpp @@ -214,12 +214,18 @@ bool LLLocalGLTFMaterial::loadMaterial() LLStringUtil::toLower(filename_lc); std::string material_name; - // Might be a good idea to make these textures into local textures - decode_successful = LLTinyGLTFHelper::getMaterialFromFile( - mFilename, - mMaterialIndex, - this, - material_name); + tinygltf::Model model; + decode_successful = LLTinyGLTFHelper::loadModel(mFilename, model); + if (decode_successful) + { + // Might be a good idea to make these textures into local textures + decode_successful = LLTinyGLTFHelper::getMaterialFromModel( + mFilename, + model, + mMaterialIndex, + this, + material_name); + } if (!material_name.empty()) { @@ -308,7 +314,10 @@ S32 LLLocalGLTFMaterialMgr::addUnit(const std::vector<std::string>& filenames) S32 LLLocalGLTFMaterialMgr::addUnit(const std::string& filename) { - S32 materials_in_file = LLTinyGLTFHelper::getMaterialCountFromFile(filename); + tinygltf::Model model; + LLTinyGLTFHelper::loadModel(filename, model); + + S32 materials_in_file = model.materials.size(); if (materials_in_file <= 0) { return 0; diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 64ce5fd4d2..4cdc503af8 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -1622,40 +1622,13 @@ static void pack_textures( } } -void LLMaterialEditor::uploadMaterialFromFile(const std::string& filename, S32 index) +void LLMaterialEditor::uploadMaterialFromModel(const std::string& filename, tinygltf::Model& model_in, S32 index) { if (index < 0 || !LLMaterialEditor::capabilitiesAvailable()) { return; } - tinygltf::TinyGLTF loader; - std::string error_msg; - std::string warn_msg; - - bool loaded = false; - tinygltf::Model model_in; - - std::string filename_lc = filename; - LLStringUtil::toLower(filename_lc); - - // Load a tinygltf model fom a file. Assumes that the input filename has already been - // been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish. - if (std::string::npos == filename_lc.rfind(".gltf")) - { // file is binary - loaded = loader.LoadBinaryFromFile(&model_in, &error_msg, &warn_msg, filename); - } - else - { // file is ascii - loaded = loader.LoadASCIIFromFile(&model_in, &error_msg, &warn_msg, filename); - } - - if (!loaded) - { - LLNotificationsUtil::add("CannotUploadMaterial"); - return; - } - if (model_in.materials.empty()) { // materials are missing @@ -1672,13 +1645,15 @@ void LLMaterialEditor::uploadMaterialFromFile(const std::string& filename, S32 i // This uses 'filename' to make sure multiple bulk uploads work // instead of fighting for a single instance. LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor", LLSD().with("filename", filename).with("index", LLSD::Integer(index))); - me->loadMaterial(model_in, filename_lc, index, false); + me->loadMaterial(model_in, filename, index, false); me->saveIfNeeded(); } void LLMaterialEditor::loadMaterialFromFile(const std::string& filename, S32 index) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; + tinygltf::TinyGLTF loader; std::string error_msg; std::string warn_msg; @@ -1725,12 +1700,12 @@ void LLMaterialEditor::loadMaterialFromFile(const std::string& filename, S32 ind if (index >= 0) { // Prespecified material - me->loadMaterial(model_in, filename_lc, index); + me->loadMaterial(model_in, filename, index); } else if (model_in.materials.size() == 1) { // Only one, just load it - me->loadMaterial(model_in, filename_lc, 0); + me->loadMaterial(model_in, filename, 0); } else { @@ -1738,6 +1713,7 @@ void LLMaterialEditor::loadMaterialFromFile(const std::string& filename, S32 ind std::list<std::string> material_list; std::vector<tinygltf::Material>::const_iterator mat_iter = model_in.materials.begin(); std::vector<tinygltf::Material>::const_iterator mat_end = model_in.materials.end(); + for (; mat_iter != mat_end; mat_iter++) { std::string mat_name = mat_iter->name; @@ -1750,10 +1726,13 @@ void LLMaterialEditor::loadMaterialFromFile(const std::string& filename, S32 ind material_list.push_back(mat_name); } } + + material_list.push_back(me->getString("material_batch_import_text")); + LLFloaterComboOptions::showUI( - [me, model_in, filename_lc](const std::string& option, S32 index) + [me, model_in, filename](const std::string& option, S32 index) { - me->loadMaterial(model_in, filename_lc, index); + me->loadMaterial(model_in, filename, index); }, me->getString("material_selection_title"), me->getString("material_selection_text"), @@ -1961,13 +1940,22 @@ void LLMaterialEditor::onSaveObjectsMaterialAsMsgCallback(const LLSD& notificati } } -void LLMaterialEditor::loadMaterial(const tinygltf::Model &model_in, const std::string &filename_lc, S32 index, bool open_floater) +const void upload_bulk(const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter type); + +void LLMaterialEditor::loadMaterial(const tinygltf::Model &model_in, const std::string &filename, S32 index, bool open_floater) { + if (index == model_in.materials.size()) + { + // bulk upload all the things + upload_bulk({ filename }, LLFilePicker::FFLOAD_MATERIAL); + return; + } + if (model_in.materials.size() <= index) { return; } - std::string folder = gDirUtilp->getDirName(filename_lc); + std::string folder = gDirUtilp->getDirName(filename); tinygltf::Material material_in = model_in.materials[index]; @@ -2055,7 +2043,7 @@ void LLMaterialEditor::loadMaterial(const tinygltf::Model &model_in, const std:: setFromGltfModel(model_in, index); - setFromGltfMetaData(filename_lc, model_in, index); + setFromGltfMetaData(filename, model_in, index); markChangesUnsaved(U32_MAX); diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h index 0401190773..6f674a4170 100644 --- a/indra/newview/llmaterialeditor.h +++ b/indra/newview/llmaterialeditor.h @@ -103,7 +103,7 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener void loadAsset() override; // @index if -1 and file contains more than one material, // will promt to select specific one - static void uploadMaterialFromFile(const std::string& filename, S32 index); + static void uploadMaterialFromModel(const std::string& filename, tinygltf::Model& model, S32 index); static void loadMaterialFromFile(const std::string& filename, S32 index = -1); void onSelectionChanged(); // live overrides selection changes @@ -237,7 +237,7 @@ private: void setFromGLTFMaterial(LLGLTFMaterial* mat); bool setFromSelection(); - void loadMaterial(const tinygltf::Model &model, const std::string &filename_lc, S32 index, bool open_floater = true); + void loadMaterial(const tinygltf::Model &model, const std::string & filename, S32 index, bool open_floater = true); friend class LLMaterialFilePicker; diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 56a48cb74d..7ae48eef8c 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -750,7 +750,9 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable // three possible file extensions, .dae .gltf .glb // check for .dae and if not then assume one of the .gl?? - if (std::string::npos != filename.rfind(".dae")) + std::string filename_lc(filename); + LLStringUtil::toLower(filename_lc); + if (std::string::npos != filename_lc.rfind(".dae")) { mModelLoader = new LLDAELoader( filename, diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 9962d0c10c..90c4436a04 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -814,8 +814,8 @@ void LLReflectionMapManager::updateUniforms() F32 minimum_ambiance = psky->getTotalReflectionProbeAmbiance(cloud_shadow_scale); F32 ambscale = gCubeSnapshot && !isRadiancePass() ? 0.f : 1.f; + F32 radscale = gCubeSnapshot && !isRadiancePass() ? 0.5f : 1.f; - for (auto* refmap : mReflectionMaps) { if (refmap == nullptr) @@ -852,7 +852,7 @@ void LLReflectionMapManager::updateUniforms() rpd.refIndex[count][3] = -rpd.refIndex[count][3]; } - rpd.refParams[count].set(llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, 0.f, 0.f, 0.f); + rpd.refParams[count].set(llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, radscale, 0.f, 0.f); S32 ni = nc; // neighbor ("index") - index into refNeighbor to write indices for current reflection probe's neighbors { diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 55cf6795fe..22c1176b05 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1847,21 +1847,11 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid) } if (mItem) { - if (te == -1) // all faces - { - LLToolDragAndDrop::dropTextureAllFaces(objectp, - mItem, - LLToolDragAndDrop::SOURCE_AGENT, - LLUUID::null); - } - else // one face - { - LLToolDragAndDrop::dropTextureOneFace(objectp, - te, - mItem, - LLToolDragAndDrop::SOURCE_AGENT, - LLUUID::null); - } + LLToolDragAndDrop::dropTextureOneFace(objectp, + te, + mItem, + LLToolDragAndDrop::SOURCE_AGENT, + LLUUID::null); } else // not an inventory item { @@ -1938,6 +1928,12 @@ void LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id) LLUUID asset_id = mMatId; if (mItem) { + // If success, the material may be copied into the object's inventory + BOOL success = LLToolDragAndDrop::handleDropMaterialProtections(objectp, mItem, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null); + if (!success) + { + return false; + } asset_id = mItem->getAssetUUID(); } diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index 1752b2494f..a609c98d61 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -675,7 +675,7 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force) LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; LLVector3 light_direction = LLVector3(LLEnvironment::instance().getClampedLightNorm().mV); - bool radiance_pass = gCubeSnapshot && !gPipeline.mReflectionMapManager.isRadiancePass(); + bool irradiance_pass = gCubeSnapshot && !gPipeline.mReflectionMapManager.isRadiancePass(); LLShaderUniforms* shader = &((LLShaderUniforms*)ptarget)[LLGLSLShader::SG_DEFAULT]; { @@ -716,15 +716,15 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force) LLColor3 ambient(getTotalAmbient()); - shader->uniform3fv(LLShaderMgr::AMBIENT, LLVector3(ambient.mV)); - - if (radiance_pass) + if (irradiance_pass) { // during an irradiance map update, disable ambient lighting (direct lighting only) and desaturate sky color (avoid tinting the world blue) shader->uniform3fv(LLShaderMgr::AMBIENT_LINEAR, LLVector3::zero.mV); + shader->uniform3fv(LLShaderMgr::AMBIENT, LLVector3::zero.mV); } else { shader->uniform3fv(LLShaderMgr::AMBIENT_LINEAR, linearColor3v(getAmbientColor() / 3.f)); // note magic number 3.f comes from SLIDER_SCALE_SUN_AMBIENT + shader->uniform3fv(LLShaderMgr::AMBIENT, LLVector3(ambient.mV)); } shader->uniform3fv(LLShaderMgr::BLUE_HORIZON_LINEAR, linearColor3v(getBlueHorizon() / 2.f)); // note magic number of 2.f comes from SLIDER_SCALE_BLUE_HORIZON_DENSITY diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 35e11b8991..92fccfcfd6 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -3095,6 +3095,60 @@ void renderAgentTarget(LLVOAvatar* avatar) } } +static void setTextureAreaDebugText(LLDrawable* drawablep) +{ + LLVOVolume* vobjp = drawablep->getVOVolume(); + + if (vobjp) + { + if (drawablep->mDistanceWRTCamera < 32.f) + { + std::ostringstream str; + + //for (S32 i = 0; i < vobjp->getNumTEs(); ++i) + S32 i = 0; + { + if (i < drawablep->getNumFaces()) + { + LLFace* facep = drawablep->getFace(i); + + if (facep) + { + LLViewerTexture* imagep = facep->getTexture(); + + if (imagep) + { + str << llformat("D - %.2f", sqrtf(imagep->getMaxVirtualSize())); + } + + imagep = vobjp->getTENormalMap(i); + + if (imagep && imagep != LLViewerFetchedTexture::sDefaultImagep) + { + str << llformat("\nN - %.2f", sqrtf(imagep->getMaxVirtualSize())); + } + + imagep = vobjp->getTESpecularMap(i); + + if (imagep && imagep != LLViewerFetchedTexture::sDefaultImagep) + { + str << llformat("\nS - %.2f", sqrtf(imagep->getMaxVirtualSize())); + } + + str << "\n\n"; + } + + vobjp->setDebugText(str.str()); + } + } + } + else + { + vobjp->setDebugText("."); + } + } +} + class LLOctreeRenderNonOccluded : public OctreeTraveler { public: @@ -3183,7 +3237,12 @@ public: size.mul(0.5f); drawBoxOutline(center, size); } - } + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) + { + setTextureAreaDebugText(drawable); + } /*if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) { @@ -3514,6 +3573,7 @@ void LLSpatialPartition::renderDebug() LLPipeline::RENDER_DEBUG_NORMALS | LLPipeline::RENDER_DEBUG_POINTS | //LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY | + LLPipeline::RENDER_DEBUG_TEXTURE_AREA | LLPipeline::RENDER_DEBUG_TEXTURE_ANIM | LLPipeline::RENDER_DEBUG_RAYCAST | LLPipeline::RENDER_DEBUG_AVATAR_VOLUME | diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index bc0eabfa0e..9b2cb0d44c 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -686,6 +686,7 @@ private: static LLFace** sNormFaces[2]; static LLFace** sSpecFaces[2]; static LLFace** sNormSpecFaces[2]; + static LLFace** sPbrFaces[2]; static LLFace** sAlphaFaces[2]; }; diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 1f4f086352..ca93eb648b 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -175,10 +175,6 @@ void LLTextureBar::draw() { color = LLColor4::green4; } - else if (mImagep->getBoostLevel() > LLGLTexture::BOOST_ALM) - { - color = LLColor4::magenta; // except none and alm - } else if (mImagep->getMaxVirtualSize() <= 0.0f) { color = LLColor4::grey; color[VALPHA] = .7f; diff --git a/indra/newview/lltinygltfhelper.cpp b/indra/newview/lltinygltfhelper.cpp index 1a8e868d11..999be07dba 100644 --- a/indra/newview/lltinygltfhelper.cpp +++ b/indra/newview/lltinygltfhelper.cpp @@ -183,19 +183,16 @@ LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tiny return rawImage; } -S32 LLTinyGLTFHelper::getMaterialCountFromFile(const std::string& filename) +bool LLTinyGLTFHelper::loadModel(const std::string& filename, tinygltf::Model& model_in) { std::string exten = gDirUtilp->getExtension(filename); - S32 materials_in_file = 0; - + if (exten == "gltf" || exten == "glb") { tinygltf::TinyGLTF loader; std::string error_msg; std::string warn_msg; - tinygltf::Model model_in; - std::string filename_lc = filename; LLStringUtil::toLower(filename_lc); @@ -217,57 +214,33 @@ S32 LLTinyGLTFHelper::getMaterialCountFromFile(const std::string& filename) << ", warning:" << warn_msg << " file: " << filename << LL_ENDL; - return 0; + return false; } if (model_in.materials.empty()) { // materials are missing LL_WARNS("GLTF") << "Cannot load. File has no materials " << filename << LL_ENDL; - return 0; + return false; } - materials_in_file = model_in.materials.size(); + + return true; } - return materials_in_file; + + + return false; } -bool LLTinyGLTFHelper::getMaterialFromFile( +bool LLTinyGLTFHelper::getMaterialFromModel( const std::string& filename, + const tinygltf::Model& model_in, S32 mat_index, LLFetchedGLTFMaterial* material, std::string& material_name) { llassert(material); - tinygltf::TinyGLTF loader; - std::string error_msg; - std::string warn_msg; - tinygltf::Model model_in; - std::string filename_lc = filename; - bool decode_successful = true; - - LLStringUtil::toLower(filename_lc); - - // Load a tinygltf model fom a file. Assumes that the input filename has already been - // been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish. - if (std::string::npos == filename_lc.rfind(".gltf")) - { // file is binary - decode_successful = loader.LoadBinaryFromFile(&model_in, &error_msg, &warn_msg, filename_lc); - } - else - { // file is ascii - decode_successful = loader.LoadASCIIFromFile(&model_in, &error_msg, &warn_msg, filename_lc); - } - - if (!decode_successful) - { - LL_WARNS("GLTF") << "Cannot load Material, error: " << error_msg - << ", warning:" << warn_msg - << " file: " << filename - << LL_ENDL; - return false; - } - else if (model_in.materials.size() <= mat_index) + if (model_in.materials.size() <= mat_index) { // materials are missing LL_WARNS("GLTF") << "Cannot load Material, Material " << mat_index << " is missing, " << filename << LL_ENDL; @@ -276,7 +249,7 @@ bool LLTinyGLTFHelper::getMaterialFromFile( material->setFromModel(model_in, mat_index); - std::string folder = gDirUtilp->getDirName(filename_lc); + std::string folder = gDirUtilp->getDirName(filename); tinygltf::Material material_in = model_in.materials[mat_index]; material_name = material_in.name; diff --git a/indra/newview/lltinygltfhelper.h b/indra/newview/lltinygltfhelper.h index 92c9876aff..256f6c854f 100644 --- a/indra/newview/lltinygltfhelper.h +++ b/indra/newview/lltinygltfhelper.h @@ -43,10 +43,11 @@ namespace LLTinyGLTFHelper LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index); - S32 getMaterialCountFromFile(const std::string& filename); + bool loadModel(const std::string& filename, tinygltf::Model& model_out); - bool getMaterialFromFile( + bool getMaterialFromModel( const std::string& filename, + const tinygltf::Model& model, S32 mat_index, LLFetchedGLTFMaterial* material, std::string& material_name); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 9743f00ab8..fb5c548b2a 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -488,14 +488,18 @@ void do_bulk_upload(std::vector<std::string> filenames, const LLSD& notification // gltf does not use normal upload procedure if (ext == "gltf" || ext == "glb") { - S32 materials_in_file = LLTinyGLTFHelper::getMaterialCountFromFile(filename); - - for (S32 i = 0; i < materials_in_file; i++) + tinygltf::Model model; + if (LLTinyGLTFHelper::loadModel(filename, model)) { - // Todo: - // 1. Decouple bulk upload from material editor - // 2. Take into account possiblity of identical textures - LLMaterialEditor::uploadMaterialFromFile(filename, i); + S32 materials_in_file = model.materials.size(); + + for (S32 i = 0; i < materials_in_file; i++) + { + // Todo: + // 1. Decouple bulk upload from material editor + // 2. Take into account possiblity of identical textures + LLMaterialEditor::uploadMaterialFromModel(filename, model, i); + } } } } @@ -530,37 +534,43 @@ bool get_bulk_upload_expected_cost(const std::vector<std::string>& filenames, S3 if (ext == "gltf" || ext == "glb") { S32 texture_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); - S32 materials_in_file = LLTinyGLTFHelper::getMaterialCountFromFile(filename); + + tinygltf::Model model; - for (S32 i = 0; i < materials_in_file; i++) + if (LLTinyGLTFHelper::loadModel(filename, model)) { - LLPointer<LLFetchedGLTFMaterial> material = new LLFetchedGLTFMaterial(); - std::string material_name; - bool decode_successful = LLTinyGLTFHelper::getMaterialFromFile(filename, i, material.get(), material_name); + S32 materials_in_file = model.materials.size(); - if (decode_successful) + for (S32 i = 0; i < materials_in_file; i++) { - // Todo: make it account for possibility of same texture in different - // materials and even in scope of same material - S32 texture_count = 0; - if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].notNull()) - { - texture_count++; - } - if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].notNull()) - { - texture_count++; - } - if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].notNull()) - { - texture_count++; - } - if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].notNull()) + LLPointer<LLFetchedGLTFMaterial> material = new LLFetchedGLTFMaterial(); + std::string material_name; + bool decode_successful = LLTinyGLTFHelper::getMaterialFromModel(filename, model, i, material.get(), material_name); + + if (decode_successful) { - texture_count++; + // Todo: make it account for possibility of same texture in different + // materials and even in scope of same material + S32 texture_count = 0; + if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].notNull()) + { + texture_count++; + } + if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].notNull()) + { + texture_count++; + } + if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].notNull()) + { + texture_count++; + } + if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].notNull()) + { + texture_count++; + } + total_cost += texture_count * texture_upload_cost; + file_count++; } - total_cost += texture_count * texture_upload_cost; - file_count++; } } } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index e217ede067..fd3c8de3e9 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -4950,10 +4950,10 @@ void LLViewerObject::updateTEMaterialTextures(U8 te) if (getTE(te)->getMaterialParams().notNull()) { const LLUUID& norm_id = getTE(te)->getMaterialParams()->getNormalID(); - mTENormalMaps[te] = LLViewerTextureManager::getFetchedTexture(norm_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM, LLViewerTexture::LOD_TEXTURE); + mTENormalMaps[te] = LLViewerTextureManager::getFetchedTexture(norm_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); const LLUUID& spec_id = getTE(te)->getMaterialParams()->getSpecularID(); - mTESpecularMaps[te] = LLViewerTextureManager::getFetchedTexture(spec_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM, LLViewerTexture::LOD_TEXTURE); + mTESpecularMaps[te] = LLViewerTextureManager::getFetchedTexture(spec_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); } LLFetchedGLTFMaterial* mat = (LLFetchedGLTFMaterial*) getTE(te)->getGLTFRenderMaterial(); @@ -4982,7 +4982,7 @@ void LLViewerObject::updateTEMaterialTextures(U8 te) } else { - img = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM, LLViewerTexture::LOD_TEXTURE); + img = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); img->addTextureStats(64.f * 64.f, TRUE); } } @@ -5140,14 +5140,14 @@ S32 LLViewerObject::setTETexture(const U8 te, const LLUUID& uuid) S32 LLViewerObject::setTENormalMap(const U8 te, const LLUUID& uuid) { LLViewerFetchedTexture *image = (uuid == LLUUID::null) ? NULL : LLViewerTextureManager::getFetchedTexture( - uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost()); + uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost()); return setTENormalMapCore(te, image); } S32 LLViewerObject::setTESpecularMap(const U8 te, const LLUUID& uuid) { LLViewerFetchedTexture *image = (uuid == LLUUID::null) ? NULL : LLViewerTextureManager::getFetchedTexture( - uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost()); + uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost()); return setTESpecularMapCore(te, image); } diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 816fa6607e..bb22d90cd9 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -815,19 +815,19 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent) mCurBin = (mCurBin + 1) % NUM_BINS; } -#if 1 +#if 0 // Slam priorities for textures that we care about (hovered, selected, and focused) // Hovered // Assumes only one level deep of parenting LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode(); - if (nodep) - { - objectp = nodep->getObject(); - if (objectp) - { - objectp->boostTexturePriority(); - } - } + if (nodep) + { + objectp = nodep->getObject(); + if (objectp) + { + objectp->boostTexturePriority(); + } + } // Focused objectp = gAgentCamera.getFocusObject(); @@ -835,6 +835,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent) { objectp->boostTexturePriority(); } +#endif // Selected struct f : public LLSelectedObjectFunctor @@ -846,7 +847,6 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent) } } func; LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func); -#endif LLVOAvatar::cullAvatarsByPixelArea(); } diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index f4f20ee7a6..31c71aac2a 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -235,7 +235,6 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderLevel(SHADER_COUNT, 0), mMaxAvatarShaderLevel(0) { - /// Make sure WL Sky is the first program //ONLY shaders that need WL Param management should be added here mShaderList.push_back(&gAvatarProgram); mShaderList.push_back(&gWaterProgram); @@ -291,6 +290,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gDeferredPBRAlphaProgram); mShaderList.push_back(&gHUDPBRAlphaProgram); mShaderList.push_back(&gDeferredSkinnedPBRAlphaProgram); + mShaderList.push_back(&gDeferredPostGammaCorrectProgram); // for gamma } @@ -2525,6 +2525,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredPostGammaCorrectProgram.addPermutation("TONEMAP_ACES_HILL_EXPOSURE_BOOST", "1"); } + else + { + gDeferredPostGammaCorrectProgram.addPermutation("TONEMAP_LINEAR", "1"); + } gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER)); gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredGammaCorrect.glsl", GL_FRAGMENT_SHADER)); gDeferredPostGammaCorrectProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index ee39b7d02f..b1abd0a656 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -570,14 +570,11 @@ void send_viewer_stats(bool include_preferences) shader_level = 3; } } - else if (gPipeline.canUseWindLightShadersOnObjects()) + else { shader_level = 2; } - else if (gPipeline.shadersLoaded()) - { - shader_level = 1; - } + system["shader_level"] = shader_level; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 578deb8b3f..ec03556ff4 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -89,8 +89,6 @@ S32 LLViewerTexture::sAuxCount = 0; LLFrameTimer LLViewerTexture::sEvaluationTimer; F32 LLViewerTexture::sDesiredDiscardBias = 0.f; F32 LLViewerTexture::sDesiredDiscardScale = 1.1f; -S8 LLViewerTexture::sCameraMovingDiscardBias = 0; -F32 LLViewerTexture::sCameraMovingBias = 0.0f; 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; @@ -103,8 +101,6 @@ F32 LLViewerTexture::sCurrentTime = 0.0f; LLViewerTexture::EDebugTexels LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_OFF; -const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve image quality by -const F32 desired_discard_bias_max = (F32)MAX_DISCARD_LEVEL; // max number of levels to reduce image quality by const F64 log_2 = log(2.0); #if ADDRESS_SIZE == 32 @@ -471,8 +467,6 @@ void LLViewerTexture::initClass() } // tuning params -const F32 discard_bias_delta = .25f; -const F32 discard_delta_time = 0.5f; const F32 GPU_MEMORY_CHECK_WAIT_TIME = 1.0f; // non-const (used externally F32 texmem_lower_bound_scale = 0.85f; @@ -552,29 +546,26 @@ void LLViewerTexture::updateClass() LLViewerMediaTexture::updateClass(); - if(isMemoryForTextureLow()) - { - // Note: isMemoryForTextureLow() uses 1s delay, make sure we waited enough for it to recheck - if (sEvaluationTimer.getElapsedTimeF32() > GPU_MEMORY_CHECK_WAIT_TIME) - { - sDesiredDiscardBias += discard_bias_delta; - sEvaluationTimer.reset(); - } - } - else if (sDesiredDiscardBias > 0.0f - && isMemoryForTextureSuficientlyFree()) - { - // If we are using less texture memory than we should, - // scale down the desired discard level - if (sEvaluationTimer.getElapsedTimeF32() > discard_delta_time) - { - sDesiredDiscardBias -= discard_bias_delta; - sEvaluationTimer.reset(); - } - } - sDesiredDiscardBias = llclamp(sDesiredDiscardBias, desired_discard_bias_min, desired_discard_bias_max); + static LLCachedControl<U32> max_vram_budget(gSavedSettings, "RenderMaxVRAMBudget", 0); + + // get an estimate of how much video memory we're using + // NOTE: our metrics miss about half the vram we use, so this biases high but turns out to typically be within 5% of the real number + F32 used = (LLImageGL::getTextureBytesAllocated() + LLVertexBuffer::getBytesAllocated()) / 1024 / 512; + + F32 budget = max_vram_budget == 0 ? gGLManager.mVRAM : max_vram_budget; + + // try to leave half a GB for everyone else, but keep at least 768MB for ourselves + F32 target = llmax(budget - 512.f, 768.f); + + F32 over_pct = llmax((used-target) / target, 0.f); + sDesiredDiscardBias = llmax(sDesiredDiscardBias, 1.f + over_pct); - LLViewerTexture::sFreezeImageUpdates = sDesiredDiscardBias > (desired_discard_bias_max - 1.0f); + if (sDesiredDiscardBias > 1.f) + { + sDesiredDiscardBias -= gFrameIntervalSeconds * 0.01; + } + + LLViewerTexture::sFreezeImageUpdates = false; // sDesiredDiscardBias > (desired_discard_bias_max - 1.0f); } //end of static functions @@ -627,7 +618,6 @@ LLViewerTexture::~LLViewerTexture() // virtual void LLViewerTexture::init(bool firstinit) { - mSelectedTime = 0.f; mMaxVirtualSize = 0.f; mMaxVirtualSizeResetInterval = 1; mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval; @@ -685,7 +675,6 @@ void LLViewerTexture::setBoostLevel(S32 level) { mBoostLevel = level; if(mBoostLevel != LLViewerTexture::BOOST_NONE && - mBoostLevel != LLViewerTexture::BOOST_ALM && mBoostLevel != LLViewerTexture::BOOST_SELECTED && mBoostLevel != LLViewerTexture::BOOST_ICON) { @@ -698,12 +687,6 @@ void LLViewerTexture::setBoostLevel(S32 level) { mMaxVirtualSize = 2048.f * 2048.f; } - - if (mBoostLevel == LLViewerTexture::BOOST_SELECTED) - { - mSelectedTime = gFrameTimeSeconds; - } - } bool LLViewerTexture::isActiveFetching() @@ -1710,10 +1693,6 @@ void LLViewerFetchedTexture::processTextureStats() { mDesiredDiscardLevel = 0; } - else if (!LLPipeline::sRenderDeferred && mBoostLevel == LLGLTexture::BOOST_ALM) - { // ??? don't load spec and normal maps when alm is disabled ??? - mDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; - } else if (mDontDiscard && mBoostLevel == LLGLTexture::BOOST_ICON) { if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) @@ -1831,8 +1810,7 @@ bool LLViewerFetchedTexture::updateFetch() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled", false); - static LLCachedControl<F32> sCameraMotionThreshold(gSavedSettings,"TextureCameraMotionThreshold", 0.2); - static LLCachedControl<S32> sCameraMotionBoost(gSavedSettings,"TextureCameraMotionBoost", 3); + if(textures_decode_disabled) // don't fetch the surface textures in wireframe mode { return false; @@ -2055,32 +2033,9 @@ bool LLViewerFetchedTexture::updateFetch() make_request = false; switchToCachedImage(); //use the cached raw data first } - //else if (!isJustBound() && mCachedRawImageReady) - //{ - // make_request = false; - //} if (make_request) { -#if 0 - // Load the texture progressively: we try not to rush to the desired discard too fast. - // If the camera is not moving, we do not tweak the discard level notch by notch but go to the desired discard with larger boosted steps - // This mitigates the "textures stay blurry" problem when loading while not killing the texture memory while moving around - S32 delta_level = (mBoostLevel > LLGLTexture::BOOST_ALM) ? 2 : 1; - if (current_discard < 0) - { - desired_discard = llmax(desired_discard, getMaxDiscardLevel() - delta_level); - } - else if (LLViewerTexture::sCameraMovingBias < sCameraMotionThreshold) - { - desired_discard = llmax(desired_discard, current_discard - sCameraMotionBoost); - } - else - { - desired_discard = llmax(desired_discard, current_discard - delta_level); - } -#endif - if (mIsFetching) { // already requested a higher resolution mip @@ -3095,10 +3050,6 @@ void LLViewerLODTexture::processTextureStats() if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 } - else if (!LLPipeline::sRenderDeferred && mBoostLevel == LLGLTexture::BOOST_ALM) - { - mDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; - } else if (mBoostLevel < LLGLTexture::BOOST_HIGH && mMaxVirtualSize <= 10.f) { // If the image has not been significantly visible in a while, we don't want it @@ -3108,72 +3059,69 @@ void LLViewerLODTexture::processTextureStats() { mDesiredDiscardLevel = getMaxDiscardLevel(); } - else - { - //static const F64 log_2 = log(2.0); - static const F64 log_4 = log(4.0); + else + { + //static const F64 log_2 = log(2.0); + static const F64 log_4 = log(4.0); - F32 discard_level = 0.f; + F32 discard_level = 0.f; - // If we know the output width and height, we can force the discard - // level to the correct value, and thus not decode more texture - // data than we need to. - if (mKnownDrawWidth && mKnownDrawHeight) - { - S32 draw_texels = mKnownDrawWidth * mKnownDrawHeight; - draw_texels = llclamp(draw_texels, MIN_IMAGE_AREA, MAX_IMAGE_AREA); + // If we know the output width and height, we can force the discard + // level to the correct value, and thus not decode more texture + // data than we need to. + if (mKnownDrawWidth && mKnownDrawHeight) + { + S32 draw_texels = mKnownDrawWidth * mKnownDrawHeight; + draw_texels = llclamp(draw_texels, MIN_IMAGE_AREA, MAX_IMAGE_AREA); - // Use log_4 because we're in square-pixel space, so an image - // with twice the width and twice the height will have mTexelsPerImage - // 4 * draw_size - discard_level = (F32)(log(mTexelsPerImage/draw_texels) / log_4); - } - else - { - // Calculate the required scale factor of the image using pixels per texel - discard_level = (F32)(log(mTexelsPerImage/mMaxVirtualSize) / log_4); - mDiscardVirtualSize = mMaxVirtualSize; - mCalculatedDiscardLevel = discard_level; - } - if (mBoostLevel < LLGLTexture::BOOST_SCULPTED) - { - discard_level += sDesiredDiscardBias; - discard_level *= sDesiredDiscardScale; // scale - discard_level += sCameraMovingDiscardBias; - } - discard_level = floorf(discard_level); + // Use log_4 because we're in square-pixel space, so an image + // with twice the width and twice the height will have mTexelsPerImage + // 4 * draw_size + discard_level = (F32)(log(mTexelsPerImage / draw_texels) / log_4); + } + else + { + // Calculate the required scale factor of the image using pixels per texel + discard_level = (F32)(log(mTexelsPerImage / mMaxVirtualSize) / log_4); + 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; - U32 desired_size = MAX_IMAGE_SIZE_DEFAULT; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 - if (mBoostLevel <= LLGLTexture::BOOST_SCULPTED) - { - desired_size = DESIRED_NORMAL_TEXTURE_SIZE; - } - if (mFullWidth > desired_size || mFullHeight > desired_size) - min_discard = 1.f; + F32 min_discard = 0.f; + U32 desired_size = MAX_IMAGE_SIZE_DEFAULT; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 + if (mBoostLevel <= LLGLTexture::BOOST_SCULPTED) + { + desired_size = DESIRED_NORMAL_TEXTURE_SIZE; + } + if (mFullWidth > desired_size || mFullHeight > desired_size) + min_discard = 1.f; - discard_level = llclamp(discard_level, min_discard, (F32)MAX_DISCARD_LEVEL); - - // Can't go higher than the max discard level - mDesiredDiscardLevel = llmin(getMaxDiscardLevel() + 1, (S32)discard_level); - // Clamp to min desired discard - mDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel, mDesiredDiscardLevel); + discard_level = llclamp(discard_level, min_discard, (F32)MAX_DISCARD_LEVEL); - // - // At this point we've calculated the quality level that we want, - // if possible. Now we check to see if we have it, and take the - // proper action if we don't. - // + // Can't go higher than the max discard level + mDesiredDiscardLevel = llmin(getMaxDiscardLevel() + 1, (S32)discard_level); + // Clamp to min desired discard + mDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel, mDesiredDiscardLevel); - S32 current_discard = getDiscardLevel(); - if (sDesiredDiscardBias > 0.0f && mBoostLevel < LLGLTexture::BOOST_SCULPTED && current_discard >= 0) - { - if(desired_discard_bias_max <= sDesiredDiscardBias && !mForceToSaveRawImage) - { - //needs to release texture memory urgently - scaleDown(); - } - } + // + // At this point we've calculated the quality level that we want, + // if possible. Now we check to see if we have it, and take the + // proper action if we don't. + // + + S32 current_discard = getDiscardLevel(); + if (mBoostLevel < LLGLTexture::BOOST_SCULPTED && current_discard >= 0) + { + if (current_discard < (mDesiredDiscardLevel-1) && !mForceToSaveRawImage) + { // should scale down + scaleDown(); + } + } if (isUpdateFrozen() // we are out of memory and nearing max allowed bias && mBoostLevel < LLGLTexture::BOOST_SCULPTED @@ -3188,6 +3136,16 @@ 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) + { + setBoostLevel(BOOST_NONE); + } } bool LLViewerLODTexture::scaleDown() diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index facf05e52f..1370f4debe 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -195,7 +195,6 @@ protected: LLUUID mID; S32 mTextureListType; // along with mID identifies where to search for this texture in TextureList - F32 mSelectedTime; // time texture was last selected mutable F32 mMaxVirtualSize = 0.f; // The largest virtual size of the image, in pixels - how much data to we need? mutable S32 mMaxVirtualSizeResetCounter; mutable S32 mMaxVirtualSizeResetInterval; @@ -223,8 +222,6 @@ public: static LLFrameTimer sEvaluationTimer; static F32 sDesiredDiscardBias; static F32 sDesiredDiscardScale; - static S8 sCameraMovingDiscardBias; - static F32 sCameraMovingBias; static S32 sMaxSculptRez ; static U32 sMinLargeImageSize ; static U32 sMaxSmallImageSize ; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 611aace4b4..0f89401bf1 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -61,6 +61,7 @@ #include "llviewerdisplay.h" #include "llviewerwindow.h" #include "llprogressview.h" + //////////////////////////////////////////////////////////////////////////// void (*LLViewerTextureList::sUUIDCallback)(void **, const LLUUID&) = NULL; @@ -533,12 +534,6 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, LLPointer<LLViewerFetchedTexture> imagep = findImage(image_id, get_element_type(boost_priority)); if (!imagep.isNull()) { - if (boost_priority != LLViewerTexture::BOOST_ALM && imagep->getBoostLevel() == LLViewerTexture::BOOST_ALM) - { - // Workaround: we need BOOST_ALM texture for something, 'rise' to NONE - imagep->setBoostLevel(LLViewerTexture::BOOST_NONE); - } - LLViewerFetchedTexture *texture = imagep.get(); if (request_from_host.isOk() && !texture->getTargetHost().isOk()) @@ -874,6 +869,8 @@ static void touch_texture(LLViewerFetchedTexture* tex, F32 vsize) } } +extern BOOL gCubeSnapshot; + void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imagep) { if (imagep->isInDebug() || imagep->isUnremovable()) @@ -882,18 +879,36 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag return; //is in debug, ignore. } + llassert(!gCubeSnapshot); + + static LLCachedControl<F32> bias_distance_scale(gSavedSettings, "TextureBiasDistanceScale", 1.f); + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE { for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) { for (U32 fi = 0; fi < imagep->getNumFaces(i); ++fi) { - const LLFace* face = (*(imagep->getFaceList(i)))[fi]; + LLFace* face = (*(imagep->getFaceList(i)))[fi]; if (face && face->getViewerObject() && face->getTextureEntry()) { - F32 vsize = face->getVirtualSize(); - + F32 vsize = face->getPixelArea(); + +#if LL_DARWIN + vsize /= 1.f + LLViewerTexture::sDesiredDiscardBias*(1.f+face->getDrawable()->mDistanceWRTCamera*bias_distance_scale); +#else + vsize /= LLViewerTexture::sDesiredDiscardBias; + vsize /= llmax(1.f, (LLViewerTexture::sDesiredDiscardBias-1.f) * (1.f + face->getDrawable()->mDistanceWRTCamera * bias_distance_scale)); + + F32 radius; + F32 cos_angle_to_view_dir; + BOOL in_frustum = face->calcPixelArea(cos_angle_to_view_dir, radius); + if (!in_frustum || !face->getDrawable()->isVisible()) + { // further reduce by discard bias when off screen or occluded + vsize /= LLViewerTexture::sDesiredDiscardBias; + } +#endif // if a GLTF material is present, ignore that face // as far as this texture stats go, but update the GLTF material // stats @@ -914,7 +929,9 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag } } } - + + //imagep->setDebugText(llformat("%.3f - %d", sqrtf(imagep->getMaxVirtualSize()), imagep->getBoostLevel())); + F32 lazy_flush_timeout = 30.f; // stop decoding F32 max_inactive_time = 20.f; // actually delete S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 5c1467f28f..ad9e3da379 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -5206,7 +5206,12 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_ LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI); } - LLPipeline::sShowHUDAttachments = FALSE; + BOOL hide_hud = LLPipeline::sShowHUDAttachments; + if (hide_hud) + { + LLPipeline::sShowHUDAttachments = FALSE; + } + LLRect window_rect = getWorldViewRectRaw(); S32 original_width = LLPipeline::sRenderDeferred ? gPipeline.mRT->deferredScreen.getWidth() : gViewerWindow->getWorldViewWidthRaw(); @@ -5276,7 +5281,10 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_ } } - LLPipeline::sShowHUDAttachments = TRUE; + if (hide_hud) + { + LLPipeline::sShowHUDAttachments = TRUE; + } setCursor(UI_CURSOR_ARROW); @@ -5351,7 +5359,11 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI); } - LLPipeline::sShowHUDAttachments = FALSE; + BOOL hide_hud = LLPipeline::sShowHUDAttachments; + if (hide_hud) + { + LLPipeline::sShowHUDAttachments = FALSE; + } LLRect window_rect = getWorldViewRectRaw(); mWorldViewRectRaw.set(0, res, res, 0); @@ -5417,7 +5429,10 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea } } - LLPipeline::sShowHUDAttachments = TRUE; + if (hide_hud) + { + LLPipeline::sShowHUDAttachments = TRUE; + } gPipeline.resetDrawOrders(); mWorldViewRectRaw = window_rect; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 42e764b492..d1f4fa1c7a 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -628,6 +628,14 @@ void LLVOVolume::animateTextures() LLGLTFMaterial *gltf_mat = te->getGLTFRenderMaterial(); const bool is_pbr = gltf_mat != nullptr; + if (!facep->mTextureMatrix) + { + facep->mTextureMatrix = new LLMatrix4(); + } + + LLMatrix4& tex_mat = *facep->mTextureMatrix; + tex_mat.setIdentity(); + if (!is_pbr) { if (!(result & LLViewerTextureAnim::ROTATE)) @@ -642,32 +650,65 @@ void LLVOVolume::animateTextures() { te->getScale(&scale_s, &scale_t); } - } - if (!facep->mTextureMatrix) - { - facep->mTextureMatrix = new LLMatrix4(); - } + LLVector3 trans ; - LLMatrix4& tex_mat = *facep->mTextureMatrix; - tex_mat.setIdentity(); + trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f)); + tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); - LLVector3 trans ; + LLVector3 scale(scale_s, scale_t, 1.f); + LLQuaternion quat; + quat.setQuat(rot, 0, 0, -1.f); + + tex_mat.rotate(quat); - trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f)); - tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); + LLMatrix4 mat; + mat.initAll(scale, LLQuaternion(), LLVector3()); + tex_mat *= mat; + + tex_mat.translate(trans); + } + else + { + if (!(result & LLViewerTextureAnim::ROTATE)) + { + rot = 0.0f; + } + if (!(result & LLViewerTextureAnim::TRANSLATE)) + { + off_s = 0.0f; + off_t = 0.0f; + } + if (!(result & LLViewerTextureAnim::SCALE)) + { + scale_s = 1.0f; + scale_t = 1.0f; + } - LLVector3 scale(scale_s, scale_t, 1.f); - LLQuaternion quat; - quat.setQuat(rot, 0, 0, -1.f); - - tex_mat.rotate(quat); + // For PBR materials, use Blinn-Phong rotation as hint for + // translation direction. In a Blinn-Phong material, the + // translation direction would be a byproduct the texture + // transform. + F32 rot_frame; + te->getRotation(&rot_frame); - LLMatrix4 mat; - mat.initAll(scale, LLQuaternion(), LLVector3()); - tex_mat *= mat; - - tex_mat.translate(trans); + tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); + + LLQuaternion quat; + quat.setQuat(rot, 0, 0, -1.f); + tex_mat.rotate(quat); + + LLMatrix4 mat; + LLVector3 scale(scale_s, scale_t, 1.f); + mat.initAll(scale, LLQuaternion(), LLVector3()); + tex_mat *= mat; + + LLVector3 off(off_s, off_t, 0.f); + off.rotVec(rot_frame, 0, 0, 1.f); + tex_mat.translate(off); + + tex_mat.translate(LLVector3(0.5f, 0.5f, 0.f)); + } } } else @@ -817,12 +858,6 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) continue; } - // clear out boost selected periodically - if (imagep->getBoostLevel() == LLGLTexture::BOOST_SELECTED) - { - imagep->setBoostLevel(LLGLTexture::BOOST_NONE); - } - F32 vsize; F32 old_size = face->getVirtualSize(); @@ -837,7 +872,6 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) else { vsize = face->getTextureVirtualSize(); - imagep->addTextureStats(vsize); } mPixelArea = llmax(mPixelArea, face->getPixelArea()); @@ -854,12 +888,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) } } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) - { - if (vsize < min_vsize) min_vsize = vsize; - if (vsize > max_vsize) max_vsize = vsize; - } - else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) { LLViewerFetchedTexture* img = LLViewerTextureManager::staticCastToFetchedTexture(imagep) ; if(img) @@ -924,7 +953,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) { LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); LLUUID id = params->getLightTexture(); - mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM); + mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE); if (mLightTexture.notNull()) { F32 rad = getLightRadius(); @@ -3266,7 +3295,6 @@ void LLVOVolume::updateSpotLightPriority() if (mLightTexture.notNull()) { mLightTexture->addTextureStats(mSpotLightPriority); - mLightTexture->setBoostLevel(LLGLTexture::BOOST_CLOUDS); } } @@ -3290,7 +3318,7 @@ LLViewerTexture* LLVOVolume::getLightTexture() { if (mLightTexture.isNull() || id != mLightTexture->getID()) { - mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM); + mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE); } } else @@ -5105,6 +5133,7 @@ LLFace** LLVolumeGeometryManager::sSimpleFaces[2] = { NULL }; LLFace** LLVolumeGeometryManager::sNormFaces[2] = { NULL }; LLFace** LLVolumeGeometryManager::sSpecFaces[2] = { NULL }; LLFace** LLVolumeGeometryManager::sNormSpecFaces[2] = { NULL }; +LLFace** LLVolumeGeometryManager::sPbrFaces[2] = { NULL }; LLFace** LLVolumeGeometryManager::sAlphaFaces[2] = { NULL }; LLVolumeGeometryManager::LLVolumeGeometryManager() @@ -5141,6 +5170,7 @@ void LLVolumeGeometryManager::allocateFaces(U32 pMaxFaceCount) sNormFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*))); sSpecFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*))); sNormSpecFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*))); + sPbrFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*))); sAlphaFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*))); } } @@ -5155,6 +5185,7 @@ void LLVolumeGeometryManager::freeFaces() ll_aligned_free<64>(sNormFaces[i]); ll_aligned_free<64>(sSpecFaces[i]); ll_aligned_free<64>(sNormSpecFaces[i]); + ll_aligned_free<64>(sPbrFaces[i]); ll_aligned_free<64>(sAlphaFaces[i]); sFullbrightFaces[i] = NULL; @@ -5163,6 +5194,7 @@ void LLVolumeGeometryManager::freeFaces() sNormFaces[i] = NULL; sSpecFaces[i] = NULL; sNormSpecFaces[i] = NULL; + sPbrFaces[i] = NULL; sAlphaFaces[i] = NULL; } } @@ -5437,7 +5469,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, llassert(type != LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_RIGGED || info->mGLTFMaterial != nullptr); llassert(type != LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK || info->mGLTFMaterial != nullptr); llassert(type != LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK_RIGGED || info->mGLTFMaterial != nullptr); - + + llassert(type != LLRenderPass::PASS_BUMP || (info->mVertexBuffer->getTypeMask() & LLVertexBuffer::MAP_TANGENT) != 0); llassert(type != LLRenderPass::PASS_NORMSPEC || info->mNormalMap.notNull()); } @@ -5596,6 +5629,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) U32 norm_count[2] = { 0 }; U32 spec_count[2] = { 0 }; U32 normspec_count[2] = { 0 }; + U32 pbr_count[2] = { 0 }; static LLCachedControl<S32> max_vbo_size(gSavedSettings, "RenderMaxVBOSize", 512); static LLCachedControl<S32> max_node_size(gSavedSettings, "RenderMaxNodeSize", 65536); @@ -5709,7 +5743,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) rigged = rigged || (vobj->isAnimatedObject() && vobj->isRiggedMesh() && vobj->getControlAvatar() && vobj->getControlAvatar()->mPlaying); - bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); bool any_rigged_face = false; //for each face @@ -5867,23 +5900,20 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) facep->mLastUpdateTime = gFrameTimeSeconds; } - if (gPipeline.canUseWindLightShadersOnObjects() - && LLPipeline::sRenderBump) { LLGLTFMaterial* gltf_mat = te->getGLTFRenderMaterial(); - if (LLPipeline::sRenderDeferred && - (gltf_mat != nullptr || (te->getMaterialParams().notNull() && !te->getMaterialID().isNull()))) + if (gltf_mat != nullptr || (te->getMaterialParams().notNull() && !te->getMaterialID().isNull())) { if (gltf_mat != nullptr) { - // all gltf materials have all vertex attributes for now - add_face(sNormSpecFaces, normspec_count, facep); + add_face(sPbrFaces, pbr_count, facep); } else { LLMaterial* mat = te->getMaterialParams().get(); - if (mat->getNormalID().notNull()) + if (mat->getNormalID().notNull() || // <-- has a normal map, needs tangents + (te->getBumpmap() && (te->getBumpmap() < 18))) // <-- has an emboss bump map, needs tangents { if (mat->getSpecularID().notNull()) { //has normal and specular maps (needs texcoord1, texcoord2, and tangent) @@ -5918,23 +5948,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) add_face(sFullbrightFaces, fullbright_count, facep); } } - else - { - if (te->getBumpmap() && LLPipeline::sRenderBump) - { //needs normal + tangent - add_face(sBumpFaces, bump_count, facep); - } - else if ((te->getShiny() && LLPipeline::sRenderBump) || - !(te->getFullbright() || bake_sunlight)) - { //needs normal - add_face(sSimpleFaces, simple_count, facep); - } - else - { //doesn't need normal - facep->setState(LLFace::FULLBRIGHT); - add_face(sFullbrightFaces, fullbright_count, facep); - } - } } } else @@ -5977,6 +5990,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) U32 normspec_mask = norm_mask | LLVertexBuffer::MAP_TEXCOORD2; U32 spec_mask = simple_mask | LLVertexBuffer::MAP_TEXCOORD2; + U32 pbr_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TANGENT; + if (emissive) { //emissive faces are present, include emissive byte to preserve batching simple_mask = simple_mask | LLVertexBuffer::MAP_EMISSIVE; @@ -5986,6 +6001,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) norm_mask = norm_mask | LLVertexBuffer::MAP_EMISSIVE; normspec_mask = normspec_mask | LLVertexBuffer::MAP_EMISSIVE; spec_mask = spec_mask | LLVertexBuffer::MAP_EMISSIVE; + pbr_mask = pbr_mask | LLVertexBuffer::MAP_EMISSIVE; } BOOL batch_textures = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1; @@ -6016,6 +6032,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) geometryBytes += genDrawInfo(group, norm_mask | extra_mask, sNormFaces[i], norm_count[i], FALSE, FALSE, rigged); geometryBytes += genDrawInfo(group, spec_mask | extra_mask, sSpecFaces[i], spec_count[i], FALSE, FALSE, rigged); geometryBytes += genDrawInfo(group, normspec_mask | extra_mask, sNormSpecFaces[i], normspec_count[i], FALSE, FALSE, rigged); + geometryBytes += genDrawInfo(group, pbr_mask | extra_mask, sPbrFaces[i], pbr_count[i], FALSE, FALSE, rigged); // for rigged set, add weights and disable alpha sorting (rigged items use depth buffer) extra_mask |= LLVertexBuffer::MAP_WEIGHT4; @@ -6158,7 +6175,7 @@ struct CompareBatchBreaker { return lte->getFullbright() < rte->getFullbright(); } - else if (LLPipeline::sRenderDeferred && lte->getMaterialID() != rte->getMaterialID()) + else if (lte->getMaterialID() != rte->getMaterialID()) { return lte->getMaterialID() < rte->getMaterialID(); } @@ -6249,13 +6266,9 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace texture_index_channels = LLGLSLShader::sIndexedTextureChannels-1; //always reserve one for shiny for now just for simplicity; } - if (LLPipeline::sRenderDeferred && distance_sort) + if (distance_sort) { texture_index_channels = gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels; - } - - if (distance_sort) - { buffer_index = -1; } @@ -6611,6 +6624,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace } else if (use_legacy_bump) { + llassert(mask & LLVertexBuffer::MAP_TANGENT); // we have a material AND legacy bump settings, but no normal map registerFace(group, facep, LLRenderPass::PASS_BUMP); } @@ -6670,7 +6684,6 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace registerFace(group, facep, LLRenderPass::PASS_ALPHA); } else if (gPipeline.shadersLoaded() - && LLPipeline::sRenderBump && te->getShiny() && can_be_shiny) { @@ -6705,7 +6718,6 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace } } else if (gPipeline.shadersLoaded() - && LLPipeline::sRenderBump && te->getShiny() && can_be_shiny) { //shiny @@ -6726,6 +6738,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace } else if (use_legacy_bump) { //register in deferred bump pass + llassert(mask& LLVertexBuffer::MAP_TANGENT); registerFace(group, facep, LLRenderPass::PASS_BUMP); } else @@ -6759,15 +6772,16 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace { registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); } - if (!hud_group && LLPipeline::sRenderBump && use_legacy_bump) + if (!hud_group && use_legacy_bump) { //if this is the deferred render and a bump map is present, register in post deferred bump registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); } } else { - if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && use_legacy_bump) + if (use_legacy_bump) { //non-shiny or fullbright deferred bump + llassert(mask& LLVertexBuffer::MAP_TANGENT); registerFace(group, facep, LLRenderPass::PASS_BUMP); } else @@ -6787,8 +6801,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace if (!gPipeline.shadersLoaded() && !is_alpha && - te->getShiny() && - LLPipeline::sRenderBump) + te->getShiny()) { //shiny as an extra pass when shaders are disabled registerFace(group, facep, LLRenderPass::PASS_SHINY); } @@ -6800,8 +6813,9 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); - if (!force_simple && LLPipeline::sRenderBump && use_legacy_bump) + if (!force_simple && use_legacy_bump) { + llassert(mask & LLVertexBuffer::MAP_TANGENT); registerFace(group, facep, LLRenderPass::PASS_BUMP); } } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 466a5d2995..e6ad42c23b 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -308,7 +308,6 @@ bool LLPipeline::sDelayVBUpdate = true; bool LLPipeline::sAutoMaskAlphaDeferred = true; bool LLPipeline::sAutoMaskAlphaNonDeferred = false; bool LLPipeline::sRenderTransparentWater = true; -bool LLPipeline::sRenderBump = true; bool LLPipeline::sBakeSunlight = false; bool LLPipeline::sNoAlpha = false; bool LLPipeline::sUseFarClip = true; @@ -335,18 +334,6 @@ static LLCullResult* sCull = NULL; void validate_framebuffer_object(); -// override the projection_matrix uniform on the given shader to that which would be set by the main camera -void set_camera_projection_matrix(LLGLSLShader& shader) -{ - auto camProj = LLViewerCamera::getInstance()->getProjection(); - glh::matrix4f projection = get_current_projection(); - projection.set_row(0, glh::vec4f(camProj.mMatrix[0][0], camProj.mMatrix[0][1], camProj.mMatrix[0][2], camProj.mMatrix[0][3])); - projection.set_row(0, glh::vec4f(camProj.mMatrix[1][0], camProj.mMatrix[1][1], camProj.mMatrix[1][2], camProj.mMatrix[1][3])); - projection.set_row(0, glh::vec4f(camProj.mMatrix[2][0], camProj.mMatrix[2][1], camProj.mMatrix[2][2], camProj.mMatrix[2][3])); - projection.set_row(0, glh::vec4f(camProj.mMatrix[3][0], camProj.mMatrix[3][1], camProj.mMatrix[3][2], camProj.mMatrix[3][3])); - shader.uniformMatrix4fv(LLShaderMgr::PROJECTION_MATRIX, 1, FALSE, projection.m); -} - // Add color attachments for deferred rendering // target -- RenderTarget to add attachments to bool addDeferredAttachments(LLRenderTarget& target, bool for_impostor = false) @@ -412,7 +399,6 @@ void LLPipeline::init() gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity"); gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize"); sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD"); - sRenderBump = TRUE; // DEPRECATED -- gSavedSettings.getBOOL("RenderObjectBump"); sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights"); sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles"); @@ -980,12 +966,6 @@ void LLPipeline::updateRenderTransparentWater() sRenderTransparentWater = gSavedSettings.getBOOL("RenderTransparentWater"); } -//static -void LLPipeline::updateRenderBump() -{ - sRenderBump = TRUE; // DEPRECATED -- gSavedSettings.getBOOL("RenderObjectBump"); -} - // static void LLPipeline::refreshCachedSettings() { @@ -1195,46 +1175,44 @@ void LLPipeline::createGLBuffers() mRT->width = 0; mRT->height = 0; - if (sRenderDeferred) - { - if (!mNoiseMap) - { - const U32 noiseRes = 128; - LLVector3 noise[noiseRes*noiseRes]; + + if (!mNoiseMap) + { + const U32 noiseRes = 128; + LLVector3 noise[noiseRes*noiseRes]; - F32 scaler = gSavedSettings.getF32("RenderDeferredNoise")/100.f; - for (U32 i = 0; i < noiseRes*noiseRes; ++i) - { - noise[i] = LLVector3(ll_frand()-0.5f, ll_frand()-0.5f, 0.f); - noise[i].normVec(); - noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f; - } + F32 scaler = gSavedSettings.getF32("RenderDeferredNoise")/100.f; + for (U32 i = 0; i < noiseRes*noiseRes; ++i) + { + noise[i] = LLVector3(ll_frand()-0.5f, ll_frand()-0.5f, 0.f); + noise[i].normVec(); + noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f; + } - LLImageGL::generateTextures(1, &mNoiseMap); + LLImageGL::generateTextures(1, &mNoiseMap); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise, false); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - } + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise, false); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } - if (!mTrueNoiseMap) + if (!mTrueNoiseMap) + { + const U32 noiseRes = 128; + F32 noise[noiseRes*noiseRes*3]; + for (U32 i = 0; i < noiseRes*noiseRes*3; i++) { - const U32 noiseRes = 128; - F32 noise[noiseRes*noiseRes*3]; - for (U32 i = 0; i < noiseRes*noiseRes*3; i++) - { - noise[i] = ll_frand()*2.0-1.0; - } - - LLImageGL::generateTextures(1, &mTrueNoiseMap); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise, false); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + noise[i] = ll_frand()*2.0-1.0; } - createLUTBuffers(); + LLImageGL::generateTextures(1, &mTrueNoiseMap); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise, false); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } + createLUTBuffers(); + gBumpImageList.restoreGL(); } @@ -1245,70 +1223,67 @@ F32 lerpf(F32 a, F32 b, F32 w) void LLPipeline::createLUTBuffers() { - if (sRenderDeferred) + if (!mLightFunc) { - if (!mLightFunc) + U32 lightResX = gSavedSettings.getU32("RenderSpecularResX"); + U32 lightResY = gSavedSettings.getU32("RenderSpecularResY"); + F32* ls = new F32[lightResX*lightResY]; + F32 specExp = gSavedSettings.getF32("RenderSpecularExponent"); + // Calculate the (normalized) blinn-phong specular lookup texture. (with a few tweaks) + for (U32 y = 0; y < lightResY; ++y) { - U32 lightResX = gSavedSettings.getU32("RenderSpecularResX"); - U32 lightResY = gSavedSettings.getU32("RenderSpecularResY"); - F32* ls = new F32[lightResX*lightResY]; - F32 specExp = gSavedSettings.getF32("RenderSpecularExponent"); - // Calculate the (normalized) blinn-phong specular lookup texture. (with a few tweaks) - for (U32 y = 0; y < lightResY; ++y) + for (U32 x = 0; x < lightResX; ++x) { - for (U32 x = 0; x < lightResX; ++x) - { - ls[y*lightResX+x] = 0; - F32 sa = (F32) x/(lightResX-1); - F32 spec = (F32) y/(lightResY-1); - F32 n = spec * spec * specExp; + ls[y*lightResX+x] = 0; + F32 sa = (F32) x/(lightResX-1); + F32 spec = (F32) y/(lightResY-1); + F32 n = spec * spec * specExp; - // Nothing special here. Just your typical blinn-phong term. - spec = powf(sa, n); + // Nothing special here. Just your typical blinn-phong term. + spec = powf(sa, n); - // Apply our normalization function. - // Note: This is the full equation that applies the full normalization curve, not an approximation. - // This is fine, given we only need to create our LUT once per buffer initialization. - spec *= (((n + 2) * (n + 4)) / (8 * F_PI * (powf(2, -n/2) + n))); - - // Since we use R16F, we no longer have a dynamic range issue we need to work around here. - // Though some older drivers may not like this, newer drivers shouldn't have this problem. - ls[y*lightResX+x] = spec; - } + // Apply our normalization function. + // Note: This is the full equation that applies the full normalization curve, not an approximation. + // This is fine, given we only need to create our LUT once per buffer initialization. + spec *= (((n + 2) * (n + 4)) / (8 * F_PI * (powf(2, -n/2) + n))); + + // Since we use R16F, we no longer have a dynamic range issue we need to work around here. + // Though some older drivers may not like this, newer drivers shouldn't have this problem. + ls[y*lightResX+x] = spec; } + } - U32 pix_format = GL_R16F; + U32 pix_format = GL_R16F; #if LL_DARWIN - // Need to work around limited precision with 10.6.8 and older drivers - // - pix_format = GL_R32F; + // Need to work around limited precision with 10.6.8 and older drivers + // + pix_format = GL_R32F; #endif - LLImageGL::generateTextures(1, &mLightFunc); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, pix_format, lightResX, lightResY, GL_RED, GL_FLOAT, ls, false); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + LLImageGL::generateTextures(1, &mLightFunc); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, pix_format, lightResX, lightResY, GL_RED, GL_FLOAT, ls, false); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - delete [] ls; - } + delete [] ls; + } - mPbrBrdfLut.allocate(512, 512, GL_RG16F); - mPbrBrdfLut.bindTarget(); - gDeferredGenBrdfLutProgram.bind(); + mPbrBrdfLut.allocate(512, 512, GL_RG16F); + mPbrBrdfLut.bindTarget(); + gDeferredGenBrdfLutProgram.bind(); - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.vertex2f(-1, -1); - gGL.vertex2f(-1, 1); - gGL.vertex2f(1, -1); - gGL.vertex2f(1, 1); - gGL.end(); - gGL.flush(); + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.vertex2f(-1, -1); + gGL.vertex2f(-1, 1); + gGL.vertex2f(1, -1); + gGL.vertex2f(1, 1); + gGL.end(); + gGL.flush(); - gDeferredGenBrdfLutProgram.unbind(); - mPbrBrdfLut.flush(); - } + gDeferredGenBrdfLutProgram.unbind(); + mPbrBrdfLut.flush(); } @@ -1343,11 +1318,6 @@ bool LLPipeline::canUseWindLightShaders() const return true; } -bool LLPipeline::canUseWindLightShadersOnObjects() const -{ - return true; -} - bool LLPipeline::canUseAntiAliasing() const { return true; @@ -4331,6 +4301,8 @@ extern std::set<LLSpatialGroup*> visible_selected_groups; void LLPipeline::renderDebug() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; + assertInitialized(); bool hud_only = hasRenderType(LLPipeline::RENDER_TYPE_HUD); @@ -4716,9 +4688,6 @@ void LLPipeline::renderDebug() bindDeferredShader(gReflectionProbeDisplayProgram, NULL); mScreenTriangleVB->setBuffer(); - // Provide our projection matrix. - set_camera_projection_matrix(gReflectionProbeDisplayProgram); - LLGLEnable blend(GL_BLEND); LLGLDepthTest depth(GL_FALSE); @@ -7410,40 +7379,6 @@ void LLPipeline::renderFinalize() if (RenderScreenSpaceReflections && !gCubeSnapshot) { -#if 0 - LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - screen space reflections"); - LL_PROFILE_GPU_ZONE("screen space reflections"); - - bindDeferredShader(gPostScreenSpaceReflectionProgram, NULL); - mScreenTriangleVB->setBuffer(); - - set_camera_projection_matrix(gPostScreenSpaceReflectionProgram); - - // We need linear depth. - static LLStaticHashedString zfar("zFar"); - static LLStaticHashedString znear("zNear"); - float nearClip = LLViewerCamera::getInstance()->getNear(); - float farClip = LLViewerCamera::getInstance()->getFar(); - gPostScreenSpaceReflectionProgram.uniform1f(zfar, farClip); - gPostScreenSpaceReflectionProgram.uniform1f(znear, nearClip); - - S32 channel = gPostScreenSpaceReflectionProgram.enableTexture(LLShaderMgr::DIFFUSE_MAP, screenTarget()->getUsage()); - if (channel > -1) - { - screenTarget()->bindTexture(0, channel, LLTexUnit::TFO_POINT); - } - - { - LLGLDisable blend(GL_BLEND); - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); - - stop_glerror(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - stop_glerror(); - } - - unbindDeferredShader(gPostScreenSpaceReflectionProgram); -#else LL_PROFILE_GPU_ZONE("ssr copy"); LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); @@ -7465,7 +7400,6 @@ void LLPipeline::renderFinalize() mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); dst.flush(); -#endif } screenTarget()->bindTarget(); @@ -8116,6 +8050,8 @@ void LLPipeline::renderDeferredLighting() soften_shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); soften_shader.uniform3fv(LLShaderMgr::LIGHTNORM, 1, environment.getClampedLightNorm().mV); + soften_shader.uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, LLDrawPoolAlpha::sWaterPlane.mV); + { LLGLDepthTest depth(GL_FALSE); LLGLDisable blend(GL_BLEND); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 483fe08559..0faa0c3f20 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -224,7 +224,6 @@ public: bool shadersLoaded(); bool canUseWindLightShaders() const; - bool canUseWindLightShadersOnObjects() const; bool canUseAntiAliasing() const; // phases @@ -421,7 +420,6 @@ public: static void setRenderHighlightTextureChannel(LLRender::eTexIndex channel); // sets which UV setup to display in highlight overlay static void updateRenderTransparentWater(); - static void updateRenderBump(); static void refreshCachedSettings(); void addDebugBlip(const LLVector3& position, const LLColor4& color); @@ -623,7 +621,6 @@ public: static bool sAutoMaskAlphaDeferred; static bool sAutoMaskAlphaNonDeferred; static bool sRenderTransparentWater; - static bool sRenderBump; static bool sBakeSunlight; static bool sNoAlpha; static bool sUseFarClip; diff --git a/indra/newview/skins/default/xui/en/floater_material_editor.xml b/indra/newview/skins/default/xui/en/floater_material_editor.xml index 6adfa40733..1c58ea6977 100644 --- a/indra/newview/skins/default/xui/en/floater_material_editor.xml +++ b/indra/newview/skins/default/xui/en/floater_material_editor.xml @@ -15,6 +15,7 @@ <string name="upload_fee_string">L$[FEE] upload fee</string> <string name="material_selection_title">Material selection</string> <string name="material_selection_text">Select material:</string> + <string name="material_batch_import_text">--- Bulk Upload All ---</string> <string name="material_override_title">Editing Material</string> <scroll_container diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml index a08831b396..534c4c3686 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml @@ -589,7 +589,7 @@ control_name="RenderDeferredSSAO" height="16" initial_value="true" - label="Ambient Occlusion" + label="Screen Space Ambient Occlusion" layout="topleft" left="420" name="UseSSAO" |