From 635c34a17bad6435f6981163660947dbf13ee763 Mon Sep 17 00:00:00 2001 From: Rye Date: Tue, 21 Jan 2025 01:19:18 -0500 Subject: Fix build with C++20 including nat's changes to fsyspath --- indra/llrender/llfontfreetype.cpp | 2 +- indra/llrender/llimagegl.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 1f14d82bf1..fa249902af 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -715,7 +715,7 @@ void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index, ll if (error == FT_Err_Out_Of_Memory) { LLError::LLUserWarningMsg::showOutOfMemory(); - LL_ERRS() << "Out of memory loading glyph for character " << wch << LL_ENDL; + LL_ERRS() << "Out of memory loading glyph for character " << U32(wch) << LL_ENDL; } std::string message = llformat( diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 3858811a50..0bfcb5d9d2 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1773,7 +1773,7 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name) ref(); LL::WorkQueue::postMaybe( mMainQueue, - [=]() + [=, this]() { LL_PROFILE_ZONE_NAMED("cglt - delete callback"); syncTexName(new_tex_name); -- cgit v1.3 From 6fcd349f374710a3f4e0e0585bb6d7af86ebb66d Mon Sep 17 00:00:00 2001 From: Rye Date: Sun, 2 Feb 2025 02:43:46 -0500 Subject: Fix Tracy memory profiling overloads for aligned allocations Fix disabling renderdoc support Improve ll_aligned_alloc functions on darwin for 32 and 64byte aligned by utilizing posix_memalign --- autobuild.xml | 14 +++---- indra/cmake/CMakeLists.txt | 1 + indra/cmake/Tracy.cmake | 6 +-- indra/llcommon/linden_common.h | 6 --- indra/llcommon/llcommon.cpp | 72 ++++++++++++++++---------------- indra/llcommon/llmemory.h | 49 +++++++++++++++++----- indra/llcommon/llprofiler.h | 32 +++++--------- indra/llrender/llglslshader.cpp | 4 +- indra/llrender/llglslshader.h | 4 +- indra/llrender/llvertexbuffer.cpp | 2 +- indra/llrender/llvertexbuffer.h | 4 +- indra/llwindow/llwindowwin32.cpp | 7 +++- indra/newview/llappviewer.cpp | 37 ++++++++-------- indra/newview/llappviewerlinux.cpp | 5 +++ indra/newview/llappviewermacosx.cpp | 5 +++ indra/newview/lldrawpool.h | 4 +- indra/newview/llheroprobemanager.cpp | 11 +++-- indra/newview/llreflectionmapmanager.cpp | 4 ++ indra/newview/llviewerdisplay.cpp | 2 + indra/newview/pipeline.cpp | 21 ++++++---- 20 files changed, 166 insertions(+), 124 deletions(-) (limited to 'indra/llrender') diff --git a/autobuild.xml b/autobuild.xml index c3df05a223..653762da9e 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -2433,11 +2433,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 226225ec049826c35adc5e897e0398ed64d4bedb + 0c3d01b7e9e39c23f0f40c56a1a04d1fba08ead0 hash_algorithm sha1 url - https://github.com/secondlife/3p-tracy/releases/download/v0.11.0%2Br1/tracy-v0.11.0.10376230034-darwin64-10376230034.tar.zst + https://github.com/secondlife/3p-tracy/releases/download/v0.11.1-r1/tracy-v0.11.1.11706699176-darwin64-11706699176.tar.zst name darwin64 @@ -2447,11 +2447,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 8c5429d1a1486f40cf7e5e88a232222d1fa4f78e + b46cef5646a8d0471ab6256fe5119220fa238772 hash_algorithm sha1 url - https://github.com/secondlife/3p-tracy/releases/download/v0.11.0%2Br1/tracy-v0.11.0.10376230034-windows64-10376230034.tar.zst + https://github.com/secondlife/3p-tracy/releases/download/v0.11.1-r1/tracy-v0.11.1.11706699176-windows64-11706699176.tar.zst name windows64 @@ -2461,11 +2461,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - ed0664a009aba1dcf1246d845839f524e857162e + beab04c9ea6036b1851a485b65c66cf6a38f0be4 hash_algorithm sha1 url - https://github.com/secondlife/3p-tracy/releases/download/v0.11.0%2Br1/tracy-v0.11.0.10376230034-linux64-10376230034.tar.zst + https://github.com/secondlife/3p-tracy/releases/download/v0.11.1-r1/tracy-v0.11.1.11706699176-linux64-11706699176.tar.zst name linux64 @@ -2478,7 +2478,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors copyright Copyright (c) 2017-2024, Bartosz Taudul (wolf@nereid.pl) version - v0.11.0.10376230034 + v0.11.1.11706699176 name tracy canonical_repo diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index cc217b0563..8d55cc4bbe 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -55,6 +55,7 @@ set(cmake_SOURCE_FILES TemplateCheck.cmake TinyEXR.cmake TinyGLTF.cmake + Tracy.cmake Tut.cmake UI.cmake UnixInstall.cmake diff --git a/indra/cmake/Tracy.cmake b/indra/cmake/Tracy.cmake index a7eac2711f..cb09337d15 100644 --- a/indra/cmake/Tracy.cmake +++ b/indra/cmake/Tracy.cmake @@ -15,6 +15,7 @@ endif() if (USE_TRACY) option(USE_TRACY_ON_DEMAND "Use on-demand Tracy profiling." ON) option(USE_TRACY_LOCAL_ONLY "Disallow remote Tracy profiling." OFF) + option(USE_TRACY_GPU "Use Tracy GPU profiling" OFF) use_system_binary(tracy) use_prebuilt_binary(tracy) @@ -31,9 +32,8 @@ if (USE_TRACY) target_compile_definitions(ll::tracy INTERFACE -DTRACY_NO_BROADCAST=1 -DTRACY_ONLY_LOCALHOST=1) endif () - # GHA runners don't always provide invariant TSC support, but always build with LL_TESTS enabled - if (DARWIN AND LL_TESTS) - target_compile_definitions(ll::tracy INTERFACE -DTRACY_TIMER_FALLBACK=1) + if (USE_TRACY_GPU AND NOT DARWIN) # Tracy OpenGL mode is incompatible with macOS/iOS + target_compile_definitions(ll::tracy INTERFACE -DLL_PROFILER_ENABLE_TRACY_OPENGL=1) endif () # See: indra/llcommon/llprofiler.h diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h index a918caa2e8..a41af153fe 100644 --- a/indra/llcommon/linden_common.h +++ b/indra/llcommon/linden_common.h @@ -28,12 +28,6 @@ #define LL_LINDEN_COMMON_H #include "llprofiler.h" -#if TRACY_ENABLE && !defined(LL_PROFILER_ENABLE_TRACY_OPENGL) // hooks for memory profiling -void *tracy_aligned_malloc(size_t size, size_t alignment); -void tracy_aligned_free(void *memblock); -#define _aligned_malloc(X, Y) tracy_aligned_malloc((X), (Y)) -#define _aligned_free(X) tracy_aligned_free((X)) -#endif // *NOTE: Please keep includes here to a minimum! // diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index 84b35749cc..7a22eaf203 100644 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -33,23 +33,23 @@ #include "lltracethreadrecorder.h" #include "llcleanup.h" -thread_local bool gProfilerEnabled = false; - -#if (TRACY_ENABLE) +#if LL_PROFILER_CONFIGURATION >= LL_PROFILER_CONFIG_TRACY && TRACY_ENABLE // Override new/delete for tracy memory profiling void* ll_tracy_new(size_t size) { - void* ptr; - if (gProfilerEnabled) - { - //LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY; - ptr = (malloc)(size); - } - else + void* ptr = (malloc)(size); + if (!ptr) { - ptr = (malloc)(size); + throw std::bad_alloc(); } + LL_PROFILE_ALLOC(ptr, size); + return ptr; +} + +void* ll_tracy_aligned_new(size_t size, size_t alignment) +{ + void* ptr = ll_aligned_malloc_fallback(size, alignment); if (!ptr) { throw std::bad_alloc(); @@ -58,6 +58,18 @@ void* ll_tracy_new(size_t size) return ptr; } +void ll_tracy_delete(void* ptr) +{ + LL_PROFILE_FREE(ptr); + (free)(ptr); +} + +void ll_tracy_aligned_delete(void* ptr) +{ + LL_PROFILE_FREE(ptr); + ll_aligned_free_fallback(ptr); +} + void* operator new(size_t size) { return ll_tracy_new(size); @@ -68,18 +80,14 @@ void* operator new[](std::size_t count) return ll_tracy_new(count); } -void ll_tracy_delete(void* ptr) +void* operator new(size_t size, std::align_val_t align) { - LL_PROFILE_FREE(ptr); - if (gProfilerEnabled) - { - //LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY; - (free)(ptr); - } - else - { - (free)(ptr); - } + return ll_tracy_aligned_new(size, (size_t)align); +} + +void* operator new[](std::size_t count, std::align_val_t align) +{ + return ll_tracy_aligned_new(count, (size_t)align); } void operator delete(void *ptr) noexcept @@ -92,27 +100,17 @@ 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. -// -// Unaligned mallocs are rare in LL code but hooking them causes problems in 3p lib code (looking at -// you, Havok), so we'll only capture the aligned version. - -void *tracy_aligned_malloc(size_t size, size_t alignment) +void operator delete(void *ptr, std::align_val_t align) noexcept { - auto ptr = ll_aligned_malloc_fallback(size, alignment); - if (ptr) LL_PROFILE_ALLOC(ptr, size); - return ptr; + ll_tracy_aligned_delete(ptr); } -void tracy_aligned_free(void *memblock) +void operator delete[](void* ptr, std::align_val_t align) noexcept { - LL_PROFILE_FREE(memblock); - ll_aligned_free_fallback(memblock); + ll_tracy_aligned_delete(ptr); } -#endif +#endif // TRACY_ENABLE && !LL_PROFILER_ENABLE_TRACY_OPENGL //static bool LLCommon::sAprInitialized = false; diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index b616edfde7..72aec57080 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -231,8 +231,6 @@ inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed wi LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY; #if defined(LL_WINDOWS) void* ret = _aligned_malloc(size, 32); -#elif defined(LL_DARWIN) - void* ret = ll_aligned_malloc_fallback( size, 32 ); #else void *ret; if (0 != posix_memalign(&ret, 32, size)) @@ -248,8 +246,31 @@ inline void ll_aligned_free_32(void *p) LL_PROFILE_FREE(p); #if defined(LL_WINDOWS) _aligned_free(p); -#elif defined(LL_DARWIN) - ll_aligned_free_fallback( p ); +#else + free(p); // posix_memalign() is compatible with heap deallocator +#endif +} + +inline void* ll_aligned_malloc_64(size_t size) // returned hunk MUST be freed with ll_aligned_free_32(). +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY; +#if defined(LL_WINDOWS) + void* ret = _aligned_malloc(size, 64); +#else + void *ret; + if (0 != posix_memalign(&ret, 64, size)) + return nullptr; +#endif + LL_PROFILE_ALLOC(ret, size); + return ret; +} + +inline void ll_aligned_free_64(void *p) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY; + LL_PROFILE_FREE(p); +#if defined(LL_WINDOWS) + _aligned_free(p); #else free(p); // posix_memalign() is compatible with heap deallocator #endif @@ -261,19 +282,23 @@ LL_FORCE_INLINE void* ll_aligned_malloc(size_t size) { LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY; void* ret; - if (LL_DEFAULT_HEAP_ALIGN % ALIGNMENT == 0) + if constexpr (LL_DEFAULT_HEAP_ALIGN % ALIGNMENT == 0) { ret = malloc(size); LL_PROFILE_ALLOC(ret, size); } - else if (ALIGNMENT == 16) + else if constexpr (ALIGNMENT == 16) { ret = ll_aligned_malloc_16(size); } - else if (ALIGNMENT == 32) + else if constexpr (ALIGNMENT == 32) { ret = ll_aligned_malloc_32(size); } + else if constexpr (ALIGNMENT == 64) + { + ret = ll_aligned_malloc_64(size); + } else { ret = ll_aligned_malloc_fallback(size, ALIGNMENT); @@ -285,16 +310,20 @@ template LL_FORCE_INLINE void ll_aligned_free(void* ptr) { LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY; - if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN) + if constexpr (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN) { LL_PROFILE_FREE(ptr); free(ptr); } - else if (ALIGNMENT == 16) + else if constexpr (ALIGNMENT == 16) { ll_aligned_free_16(ptr); } - else if (ALIGNMENT == 32) + else if constexpr (ALIGNMENT == 32) + { + return ll_aligned_free_32(ptr); + } + else if constexpr (ALIGNMENT == 64) { return ll_aligned_free_32(ptr); } diff --git a/indra/llcommon/llprofiler.h b/indra/llcommon/llprofiler.h index f6a4d24747..5fb32d6280 100644 --- a/indra/llcommon/llprofiler.h +++ b/indra/llcommon/llprofiler.h @@ -74,23 +74,18 @@ #define LL_PROFILER_CONFIGURATION LL_PROFILER_CONFIG_FAST_TIMER #endif -extern thread_local bool gProfilerEnabled; - #if defined(LL_PROFILER_CONFIGURATION) && (LL_PROFILER_CONFIGURATION > LL_PROFILER_CONFIG_NONE) #if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY || LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER #include "tracy/Tracy.hpp" - // Enable OpenGL profiling - #define LL_PROFILER_ENABLE_TRACY_OPENGL 0 - // Enable RenderDoc labeling - #define LL_PROFILER_ENABLE_RENDER_DOC 0 + //#define LL_PROFILER_ENABLE_RENDER_DOC 0 #endif #if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY #define LL_PROFILER_FRAME_END FrameMark - #define LL_PROFILER_SET_THREAD_NAME( name ) tracy::SetThreadName( name ); gProfilerEnabled = true; + #define LL_PROFILER_SET_THREAD_NAME( name ) tracy::SetThreadName( name ); #define LL_RECORD_BLOCK_TIME(name) ZoneScoped // Want descriptive names; was: ZoneNamedN( ___tracy_scoped_zone, #name, true ); #define LL_PROFILE_ZONE_NAMED(name) ZoneNamedN( ___tracy_scoped_zone, name, true ); #define LL_PROFILE_ZONE_NAMED_COLOR(name,color) ZoneNamedNC( ___tracy_scopped_zone, name, color, true ) // RGB @@ -133,7 +128,7 @@ extern thread_local bool gProfilerEnabled; #endif #if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER #define LL_PROFILER_FRAME_END FrameMark - #define LL_PROFILER_SET_THREAD_NAME( name ) tracy::SetThreadName( name ); gProfilerEnabled = true; + #define LL_PROFILER_SET_THREAD_NAME( name ) tracy::SetThreadName( name ); #define LL_RECORD_BLOCK_TIME(name) ZoneNamedN(___tracy_scoped_zone, #name, true); const LLTrace::BlockTimer& LL_GLUE_TOKENS(block_time_recorder, __LINE__)(LLTrace::timeThisBlock(name)); (void)LL_GLUE_TOKENS(block_time_recorder, __LINE__); #define LL_PROFILE_ZONE_NAMED(name) ZoneNamedN( ___tracy_scoped_zone, #name, true ); #define LL_PROFILE_ZONE_NAMED_COLOR(name,color) ZoneNamedNC( ___tracy_scopped_zone, name, color, true ) // RGB @@ -158,23 +153,20 @@ extern thread_local bool gProfilerEnabled; #endif // LL_PROFILER #if LL_PROFILER_ENABLE_TRACY_OPENGL -#define LL_PROFILE_GPU_ZONE(name) TracyGpuZone(name) -#define LL_PROFILE_GPU_ZONEC(name,color) TracyGpuZoneC(name,color) +#define LL_PROFILE_GPU_ZONE(name) TracyGpuZone(name) +#define LL_PROFILE_GPU_ZONEC(name,color) TracyGpuZoneC(name,color) #define LL_PROFILER_GPU_COLLECT TracyGpuCollect #define LL_PROFILER_GPU_CONTEXT TracyGpuContext - -// disable memory tracking (incompatible with GPU tracing -#define LL_PROFILE_ALLOC(ptr, size) (void)(ptr); (void)(size); -#define LL_PROFILE_FREE(ptr) (void)(ptr); +#define LL_PROFILER_GPU_CONTEXT_NAMED TracyGpuContextName #else -#define LL_PROFILE_GPU_ZONE(name) (void)name; -#define LL_PROFILE_GPU_ZONEC(name,color) (void)name;(void)color; +#define LL_PROFILE_GPU_ZONE(name) (void)name; +#define LL_PROFILE_GPU_ZONEC(name,color) (void)name;(void)color; #define LL_PROFILER_GPU_COLLECT #define LL_PROFILER_GPU_CONTEXT +#define LL_PROFILER_GPU_CONTEXT_NAMED(name) (void)name; +#endif // LL_PROFILER_ENABLE_TRACY_OPENGL -#define LL_LABEL_OBJECT_GL(type, name, length, label) - -#if !LL_DARWIN && LL_PROFILER_CONFIGURATION > 1 +#if LL_PROFILER_CONFIGURATION >= LL_PROFILER_CONFIG_TRACY #define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size) #define LL_PROFILE_FREE(ptr) TracyFree(ptr) #else @@ -182,8 +174,6 @@ extern thread_local bool gProfilerEnabled; #define LL_PROFILE_FREE(ptr) (void)(ptr); #endif -#endif - #if LL_PROFILER_ENABLE_RENDER_DOC #define LL_LABEL_OBJECT_GL(type, name, length, label) glObjectLabel(type, name, length, label) #else diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index b3f32fdc83..0841c0e943 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -543,7 +543,7 @@ bool LLGLSLShader::createShader() } } -#ifdef LL_PROFILER_ENABLE_RENDER_DOC +#if LL_PROFILER_ENABLE_RENDER_DOC setLabel(mName.c_str()); #endif @@ -2061,7 +2061,7 @@ LLUUID LLGLSLShader::hash() return hash_obj.digest(); } -#ifdef LL_PROFILER_ENABLE_RENDER_DOC +#if LL_PROFILER_ENABLE_RENDER_DOC void LLGLSLShader::setLabel(const char* label) { LL_LABEL_OBJECT_GL(GL_PROGRAM, mProgramObject, strlen(label), label); } diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 58c456f134..cade888a83 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -360,7 +360,7 @@ public: // hacky flag used for optimization in LLDrawPoolAlpha bool mCanBindFast = false; -#ifdef LL_PROFILER_ENABLE_RENDER_DOC +#if LL_PROFILER_ENABLE_RENDER_DOC void setLabel(const char* label); #endif @@ -380,7 +380,7 @@ extern LLGLSLShader gSolidColorProgram; //Alpha mask shader (declared here so llappearance can access properly) extern LLGLSLShader gAlphaMaskProgram; -#ifdef LL_PROFILER_ENABLE_RENDER_DOC +#if LL_PROFILER_ENABLE_RENDER_DOC #define LL_SET_SHADER_LABEL(shader) shader.setLabel(#shader) #else #define LL_SET_SHADER_LABEL(shader, label) diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 1f0c424188..86ec9a453b 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -885,7 +885,7 @@ bool LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of return true; } -#ifdef LL_PROFILER_ENABLE_RENDER_DOC +#if LL_PROFILER_ENABLE_RENDER_DOC void LLVertexBuffer::setLabel(const char* label) { LL_LABEL_OBJECT_GL(GL_BUFFER, mGLBuffer, strlen(label), label); } diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 375ad76fb8..faaa6ba0f0 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -279,7 +279,7 @@ public: //for debugging, validate data in given range is valid bool validateRange(U32 start, U32 end, U32 count, U32 offset) const; - #ifdef LL_PROFILER_ENABLE_RENDER_DOC + #if LL_PROFILER_ENABLE_RENDER_DOC void setLabel(const char* label); #endif @@ -340,7 +340,7 @@ public: static U32 sVertexCount; }; -#ifdef LL_PROFILER_ENABLE_RENDER_DOC +#if LL_PROFILER_ENABLE_RENDER_DOC #define LL_LABEL_VERTEX_BUFFER(buf, name) buf->setLabel(name) #else #define LL_LABEL_VERTEX_BUFFER(buf, name) diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 832cf254d1..90713a6653 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1666,6 +1666,11 @@ const S32 max_format = (S32)num_formats - 1; return false; } + // Setup Tracy gpu context + { + LL_PROFILER_GPU_CONTEXT; + } + // Disable vertical sync for swap toggleVSync(enable_vsync); @@ -1697,8 +1702,6 @@ const S32 max_format = (S32)num_formats - 1; swapBuffers(); } - LL_PROFILER_GPU_CONTEXT; - return true; } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 9889765fff..84cce2348a 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1324,6 +1324,7 @@ bool LLAppViewer::frame() bool LLAppViewer::doFrame() { LL_RECORD_BLOCK_TIME(FTM_FRAME); + LL_PROFILE_GPU_ZONE("Frame"); { // and now adjust the visuals from previous frame. if(LLPerfStats::tunables.userAutoTuneEnabled && LLPerfStats::tunables.tuningFlag != LLPerfStats::Tunables::Nothing) @@ -1413,24 +1414,26 @@ bool LLAppViewer::doFrame() if (!LLApp::isExiting()) { - LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df JoystickKeyboard"); - pingMainloopTimeout("Main:JoystickKeyboard"); - - // Scan keyboard for movement keys. Command keys and typing - // are handled by windows callbacks. Don't do this until we're - // done initializing. JC - if (gViewerWindow - && (gHeadlessClient || gViewerWindow->getWindow()->getVisible()) - && gViewerWindow->getActive() - && !gViewerWindow->getWindow()->getMinimized() - && LLStartUp::getStartupState() == STATE_STARTED - && (gHeadlessClient || !gViewerWindow->getShowProgress()) - && !gFocusMgr.focusLocked()) { - LLPerfStats::RecordSceneTime T (LLPerfStats::StatType_t::RENDER_IDLE); - joystick->scanJoystick(); - gKeyboard->scanKeyboard(); - gViewerInput.scanMouse(); + LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df JoystickKeyboard"); + pingMainloopTimeout("Main:JoystickKeyboard"); + + // Scan keyboard for movement keys. Command keys and typing + // are handled by windows callbacks. Don't do this until we're + // done initializing. JC + if (gViewerWindow + && (gHeadlessClient || gViewerWindow->getWindow()->getVisible()) + && gViewerWindow->getActive() + && !gViewerWindow->getWindow()->getMinimized() + && LLStartUp::getStartupState() == STATE_STARTED + && (gHeadlessClient || !gViewerWindow->getShowProgress()) + && !gFocusMgr.focusLocked()) + { + LLPerfStats::RecordSceneTime T(LLPerfStats::StatType_t::RENDER_IDLE); + joystick->scanJoystick(); + gKeyboard->scanKeyboard(); + gViewerInput.scanMouse(); + } } // Update state based on messages, user input, object idle. diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index 1709970156..89d19d180b 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -73,6 +73,11 @@ static void exceptionTerminateHandler() int main( int argc, char **argv ) { + // Call Tracy first thing to have it allocate memory + // https://github.com/wolfpld/tracy/issues/196 + LL_PROFILER_FRAME_END; + LL_PROFILER_SET_THREAD_NAME("App"); + gArgC = argc; gArgV = argv; diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 4162c0479a..f497a3cdf3 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -231,6 +231,11 @@ void infos(const std::string& message) int main( int argc, char **argv ) { + // Call Tracy first thing to have it allocate memory + // https://github.com/wolfpld/tracy/issues/196 + LL_PROFILER_FRAME_END; + LL_PROFILER_SET_THREAD_NAME("App"); + // Store off the command line args for use later. gArgC = argc; gArgV = argv; diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index 1c8864a9df..46696fc4a4 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -204,7 +204,7 @@ public: NUM_RENDER_TYPES, }; - #ifdef LL_PROFILER_ENABLE_RENDER_DOC + #if LL_PROFILER_ENABLE_RENDER_DOC static inline const char* lookupPassName(U32 pass) { switch (pass) @@ -340,7 +340,7 @@ public: } } #else - static inline const char* lookupPass(U32 pass) { return ""; } + static inline const char* lookupPassName(U32 pass) { return ""; } #endif LLRenderPass(const U32 type); diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index e754de2fd1..2ec161c093 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -81,6 +81,7 @@ void LLHeroProbeManager::update() } LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + LL_PROFILE_GPU_ZONE("hero manager update"); llassert(!gCubeSnapshot); // assert a snapshot is not in progress if (LLAppViewer::instance()->logoutRequestSent()) { @@ -282,6 +283,9 @@ void LLHeroProbeManager::renderProbes() // In effect this simulates single-bounce lighting. void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool is_dynamic, F32 near_clip) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + LL_PROFILE_GPU_ZONE("hero probe update"); + // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mHeroProbeRT; @@ -352,7 +356,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool for (int i = 0; i < mMipChain.size(); ++i) { - LL_PROFILE_GPU_ZONE("probe mip"); + LL_PROFILE_GPU_ZONE("hero probe mip"); mMipChain[i].bindTarget(); if (i == 0) { @@ -379,7 +383,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool if (mip >= 0) { - LL_PROFILE_GPU_ZONE("probe mip copy"); + LL_PROFILE_GPU_ZONE("hero probe mip copy"); mTexture->bind(0); glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res); @@ -427,7 +431,7 @@ void LLHeroProbeManager::generateRadiance(LLReflectionMap* probe) for (int i = 0; i < mMipChain.size() / 4; ++i) { - LL_PROFILE_GPU_ZONE("probe radiance gen"); + LL_PROFILE_GPU_ZONE("hero probe radiance gen"); static LLStaticHashedString sMipLevel("mipLevel"); static LLStaticHashedString sRoughness("roughness"); static LLStaticHashedString sWidth("u_width"); @@ -474,6 +478,7 @@ void LLHeroProbeManager::updateUniforms() } LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + LL_PROFILE_GPU_ZONE("hpmu - uniforms") LLMatrix4a modelview; modelview.loadu(gGLModelView); diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 4760ab376e..ae5ade5f24 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -210,6 +210,7 @@ void LLReflectionMapManager::update() } LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + LL_PROFILE_GPU_ZONE("reflection manager update"); llassert(!gCubeSnapshot); // assert a snapshot is not in progress if (LLAppViewer::instance()->logoutRequestSent()) { @@ -696,6 +697,8 @@ void LLReflectionMapManager::doProbeUpdate() // In effect this simulates single-bounce lighting. void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + LL_PROFILE_GPU_ZONE("probe update"); // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mAuxillaryRT; @@ -1011,6 +1014,7 @@ void LLReflectionMapManager::updateUniforms() } LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + LL_PROFILE_GPU_ZONE("rmmu - uniforms") // structure for packing uniform buffer object // see class3/deferred/reflectionProbeF.glsl diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 32019f860d..b34c8600f7 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -407,6 +407,7 @@ static void update_tp_display(bool minimized) void display(bool rebuild, F32 zoom_factor, int subfield, bool for_snapshot) { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Render"); + LL_PROFILE_GPU_ZONE("Render"); LLPerfStats::RecordSceneTime T (LLPerfStats::StatType_t::RENDER_DISPLAY); // render time capture - This is the main stat for overall rendering. @@ -709,6 +710,7 @@ void display(bool rebuild, F32 zoom_factor, int subfield, bool for_snapshot) if (gPipeline.RenderMirrors && !gSnapshot) { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Update hero probes"); + LL_PROFILE_GPU_ZONE("hero manager") gPipeline.mHeroProbeManager.update(); gPipeline.mHeroProbeManager.renderProbes(); } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 18dd694246..ddfb5a5621 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -7182,11 +7182,11 @@ extern LLPointer gEXRImage; void LLPipeline::tonemap(LLRenderTarget* src, LLRenderTarget* dst) { + LL_PROFILE_GPU_ZONE("tonemap"); + dst->bindTarget(); // gamma correct lighting { - LL_PROFILE_GPU_ZONE("tonemap"); - static LLCachedControl buildNoPost(gSavedSettings, "RenderDisablePostProcessing", false); LLGLDepthTest depth(GL_FALSE, GL_FALSE); @@ -7235,11 +7235,11 @@ void LLPipeline::tonemap(LLRenderTarget* src, LLRenderTarget* dst) void LLPipeline::gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst) { + LL_PROFILE_GPU_ZONE("gamma correct"); + dst->bindTarget(); // gamma correct lighting { - LL_PROFILE_GPU_ZONE("gamma correct"); - LLGLDepthTest depth(GL_FALSE, GL_FALSE); static LLCachedControl buildNoPost(gSavedSettings, "RenderDisablePostProcessing", false); @@ -7290,9 +7290,9 @@ void LLPipeline::copyScreenSpaceReflections(LLRenderTarget* src, LLRenderTarget* void LLPipeline::generateGlow(LLRenderTarget* src) { + LL_PROFILE_GPU_ZONE("glow generate"); if (sRenderGlow) { - LL_PROFILE_GPU_ZONE("glow"); mGlow[2].bindTarget(); mGlow[2].clear(); @@ -7401,6 +7401,7 @@ void LLPipeline::generateGlow(LLRenderTarget* src) void LLPipeline::applyCAS(LLRenderTarget* src, LLRenderTarget* dst) { static LLCachedControl cas_sharpness(gSavedSettings, "RenderCASSharpness", 0.4f); + LL_PROFILE_GPU_ZONE("cas"); if (cas_sharpness == 0.0f || !gCASProgram.isComplete()) { gPipeline.copyRenderTarget(src, dst); @@ -7445,6 +7446,7 @@ void LLPipeline::applyCAS(LLRenderTarget* src, LLRenderTarget* dst) void LLPipeline::applyFXAA(LLRenderTarget* src, LLRenderTarget* dst) { + LL_PROFILE_GPU_ZONE("FXAA"); { llassert(!gCubeSnapshot); bool multisample = RenderFSAAType == 1 && gFXAAProgram[0].isComplete() && mFXAAMap.isComplete(); @@ -7536,7 +7538,7 @@ void LLPipeline::generateSMAABuffers(LLRenderTarget* src) // Present everything. if (multisample) { - LL_PROFILE_GPU_ZONE("aa"); + LL_PROFILE_GPU_ZONE("SMAA Edge"); static LLCachedControl aa_quality(gSavedSettings, "RenderFSAASamples", 0U); U32 fsaa_quality = std::clamp(aa_quality(), 0U, 3U); @@ -7648,13 +7650,13 @@ void LLPipeline::generateSMAABuffers(LLRenderTarget* src) void LLPipeline::applySMAA(LLRenderTarget* src, LLRenderTarget* dst) { + LL_PROFILE_GPU_ZONE("SMAA"); llassert(!gCubeSnapshot); bool multisample = RenderFSAAType == 2 && gSMAAEdgeDetectProgram[0].isComplete() && mFXAAMap.isComplete() && mSMAABlendBuffer.isComplete(); // Present everything. if (multisample) { - LL_PROFILE_GPU_ZONE("aa"); static LLCachedControl aa_quality(gSavedSettings, "RenderFSAASamples", 0U); U32 fsaa_quality = std::clamp(aa_quality(), 0U, 3U); @@ -7732,8 +7734,9 @@ void LLPipeline::copyRenderTarget(LLRenderTarget* src, LLRenderTarget* dst) void LLPipeline::combineGlow(LLRenderTarget* src, LLRenderTarget* dst) { - // Go ahead and do our glow combine here in our destination. We blit this later into the front buffer. + LL_PROFILE_GPU_ZONE("glow combine"); + // Go ahead and do our glow combine here in our destination. We blit this later into the front buffer. dst->bindTarget(); { @@ -7752,6 +7755,7 @@ void LLPipeline::combineGlow(LLRenderTarget* src, LLRenderTarget* dst) void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst) { + LL_PROFILE_GPU_ZONE("dof"); { bool dof_enabled = (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) && @@ -7762,7 +7766,6 @@ void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst) if (dof_enabled) { - LL_PROFILE_GPU_ZONE("dof"); LLGLDisable blend(GL_BLEND); // depth of field focal plane calculations -- cgit v1.3 From 2f39d381efaa77f27f6daf10b782066e426872b6 Mon Sep 17 00:00:00 2001 From: Rye Date: Sat, 16 Nov 2024 03:51:33 -0500 Subject: Restore support for anistropic filtering on macos --- indra/llrender/llgl.cpp | 7 ++++++- indra/llrender/llrender.cpp | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 1bc5e79835..008ee8d450 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -1266,7 +1266,7 @@ bool LLGLManager::initGL() // there's some implementation that reports a crazy value mMaxUniformBlockSize = llmin(mMaxUniformBlockSize, 65536); - if (mGLVersion >= 4.59f) + if (mHasAnisotropic) { glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &mMaxAnisotropy); } @@ -1430,6 +1430,11 @@ void LLGLManager::initExtensions() mHasCubeMapArray = mGLVersion >= 3.99f; mHasTransformFeedback = mGLVersion >= 3.99f; mHasDebugOutput = mGLVersion >= 4.29f; + mHasAnisotropic = mGLVersion >= 4.59f; + if(!mHasAnisotropic && gGLHExts.mSysExts) + { + mHasAnisotropic = ExtensionExists("GL_EXT_texture_filter_anisotropic", gGLHExts.mSysExts); + } // Misc glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*) &mGLMaxVertexRange); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 1dc87a66ce..ec76aa4f36 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -511,7 +511,7 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio } } - if (gGLManager.mGLVersion >= 4.59f) + if (gGLManager.mHasAnisotropic) { if (LLImageGL::sGlobalUseAnisotropic && option == TFO_ANISOTROPIC) { -- cgit v1.3 From 0fbc30df543293697597a9a46cca611d596a443a Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Wed, 2 Oct 2024 19:57:27 +0300 Subject: Merge pull request #2758 from Nicky-D/feature/fontcache Port Fontcache from Firestorm. --- indra/llrender/llfontfreetype.cpp | 201 +++++++++++++++++--------------------- indra/llrender/llfontfreetype.h | 23 +++-- 2 files changed, 105 insertions(+), 119 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index fa249902af..bab721615b 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -56,9 +56,9 @@ FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL; -LLFontManager *gFontManagerp = NULL; +LLFontManager *gFontManagerp = nullptr; -FT_Library gFTLibrary = NULL; +FT_Library gFTLibrary = nullptr; //static void LLFontManager::initClass() @@ -73,7 +73,7 @@ void LLFontManager::initClass() void LLFontManager::cleanupClass() { delete gFontManagerp; - gFontManagerp = NULL; + gFontManagerp = nullptr; } LLFontManager::LLFontManager() @@ -101,6 +101,7 @@ LLFontManager::LLFontManager() LLFontManager::~LLFontManager() { FT_Done_FreeType(gFTLibrary); + unloadAllFonts(); } @@ -139,12 +140,8 @@ LLFontFreetype::LLFontFreetype() mAscender(0.f), mDescender(0.f), mLineHeight(0.f), -#ifdef LL_WINDOWS - pFileStream(NULL), - pFtStream(NULL), -#endif mIsFallback(false), - mFTFace(NULL), + mFTFace(nullptr), mRenderGlyphCount(0), mAddGlyphCount(0), mStyle(0), @@ -158,35 +155,16 @@ LLFontFreetype::~LLFontFreetype() // Clean up freetype libs. if (mFTFace) FT_Done_Face(mFTFace); - mFTFace = NULL; + mFTFace = nullptr; // Delete glyph info std::for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer()); mCharGlyphInfoMap.clear(); -#ifdef LL_WINDOWS - delete pFileStream; // closed by FT_Done_Face - delete pFtStream; -#endif delete mFontBitmapCachep; // mFallbackFonts cleaned up by LLPointer destructor } -#ifdef LL_WINDOWS -unsigned long ft_read_cb(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count) { - if (count <= 0) return count; - llifstream *file_stream = static_cast(stream->descriptor.pointer); - file_stream->seekg(offset, std::ios::beg); - file_stream->read((char*)buffer, count); - return (unsigned long)file_stream->gcount(); -} - -void ft_close_cb(FT_Stream stream) { - llifstream *file_stream = static_cast(stream->descriptor.pointer); - file_stream->close(); -} -#endif - bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool is_fallback, S32 face_n) { // Don't leak face objects. This is also needed to deal with @@ -194,26 +172,21 @@ bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v if (mFTFace) { FT_Done_Face(mFTFace); - mFTFace = NULL; + mFTFace = nullptr; } - int error; -#ifdef LL_WINDOWS - error = ftOpenFace(filename, face_n); -#else - error = FT_New_Face( gFTLibrary, - filename.c_str(), - 0, - &mFTFace); -#endif + FT_Open_Args openArgs; + memset( &openArgs, 0, sizeof( openArgs ) ); + openArgs.memory_base = gFontManagerp->loadFont( filename, openArgs.memory_size ); + + if( !openArgs.memory_base ) + return false; + + openArgs.flags = FT_OPEN_MEMORY; + int error = FT_Open_Face( gFTLibrary, &openArgs, 0, &mFTFace ); if (error) - { -#ifdef LL_WINDOWS - clearFontStreams(); -#endif return false; - } mIsFallback = is_fallback; F32 pixels_per_em = (point_size / 72.f)*vert_dpi; // Size in inches * dpi @@ -228,10 +201,8 @@ bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v { // Clean up freetype libs. FT_Done_Face(mFTFace); -#ifdef LL_WINDOWS - clearFontStreams(); -#endif - mFTFace = NULL; + + mFTFace = nullptr; return false; } @@ -287,73 +258,30 @@ S32 LLFontFreetype::getNumFaces(const std::string& filename) if (mFTFace) { FT_Done_Face(mFTFace); - mFTFace = NULL; + mFTFace = nullptr; } S32 num_faces = 1; -#ifdef LL_WINDOWS - int error = ftOpenFace(filename, 0); + FT_Open_Args openArgs; + memset( &openArgs, 0, sizeof( openArgs ) ); + openArgs.memory_base = gFontManagerp->loadFont( filename, openArgs.memory_size ); + if( !openArgs.memory_base ) + return 0; + openArgs.flags = FT_OPEN_MEMORY; + int error = FT_Open_Face( gFTLibrary, &openArgs, 0, &mFTFace ); if (error) - { return 0; - } else - { num_faces = mFTFace->num_faces; - } FT_Done_Face(mFTFace); - clearFontStreams(); - mFTFace = NULL; -#endif + mFTFace = nullptr; return num_faces; } -#ifdef LL_WINDOWS -S32 LLFontFreetype::ftOpenFace(const std::string& filename, S32 face_n) -{ - S32 error = -1; - pFileStream = new llifstream(filename, std::ios::binary); - if (pFileStream->is_open()) - { - std::streampos beg = pFileStream->tellg(); - pFileStream->seekg(0, std::ios::end); - std::streampos end = pFileStream->tellg(); - std::size_t file_size = end - beg; - pFileStream->seekg(0, std::ios::beg); - - pFtStream = new LLFT_Stream(); - pFtStream->base = 0; - pFtStream->pos = 0; - pFtStream->size = static_cast(file_size); - pFtStream->descriptor.pointer = pFileStream; - pFtStream->read = ft_read_cb; - pFtStream->close = ft_close_cb; - - FT_Open_Args args; - args.flags = FT_OPEN_STREAM; - args.stream = (FT_StreamRec*)pFtStream; - error = FT_Open_Face(gFTLibrary, &args, face_n, &mFTFace); - } - return error; -} - -void LLFontFreetype::clearFontStreams() -{ - if (pFileStream) - { - pFileStream->close(); - } - delete pFileStream; - delete pFtStream; - pFileStream = NULL; - pFtStream = NULL; -} -#endif - void LLFontFreetype::addFallbackFont(const LLPointer& fallback_font, const char_functor_t& functor) { @@ -377,7 +305,7 @@ F32 LLFontFreetype::getDescenderHeight() const F32 LLFontFreetype::getXAdvance(llwchar wch) const { - if (mFTFace == NULL) + if (mFTFace == nullptr) return 0.0; // Return existing info only if it is current @@ -401,7 +329,7 @@ F32 LLFontFreetype::getXAdvance(llwchar wch) const F32 LLFontFreetype::getXAdvance(const LLFontGlyphInfo* glyph) const { - if (mFTFace == NULL) + if (mFTFace == nullptr) return 0.0; return glyph->mXAdvance; @@ -409,7 +337,7 @@ F32 LLFontFreetype::getXAdvance(const LLFontGlyphInfo* glyph) const F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const { - if (mFTFace == NULL) + if (mFTFace == nullptr) return 0.0; //llassert(!mIsFallback); @@ -428,7 +356,7 @@ F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const F32 LLFontFreetype::getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const { - if (mFTFace == NULL) + if (mFTFace == nullptr) return 0.0; U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0; @@ -451,7 +379,7 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch, EFontGlyphType glyph_type { if (!mFTFace) { - return NULL; + return nullptr; } llassert(!mIsFallback); @@ -542,14 +470,14 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch, EFontGlyphType glyph_type { return addGlyphFromFont(this, wch, glyph_index, glyph_type); } - return NULL; + return nullptr; } LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index, EFontGlyphType requested_glyph_type) const { LL_PROFILE_ZONE_SCOPED; - if (mFTFace == NULL) - return NULL; + if (mFTFace == nullptr) + return nullptr; llassert(!mIsFallback); fontp->renderGlyph(requested_glyph_type, glyph_index, wch); @@ -602,7 +530,7 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l { U8 *buffer_data = fontp->mFTFace->glyph->bitmap.buffer; S32 buffer_row_stride = fontp->mFTFace->glyph->bitmap.pitch; - U8 *tmp_graydata = NULL; + U8 *tmp_graydata = nullptr; if (fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) @@ -699,7 +627,7 @@ void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index, llwchar wch) const { - if (mFTFace == NULL) + if (mFTFace == nullptr) return; FT_Int32 load_flags = FT_LOAD_FORCE_AUTOHINT; @@ -901,3 +829,58 @@ void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 } } + +namespace ll +{ + namespace fonts + { + class LoadedFont + { + public: + LoadedFont( std::string aName , std::string const &aAddress, std::size_t aSize ) + : mAddress( aAddress ) + { + mName = aName; + mSize = aSize; + mRefs = 1; + } + std::string mName; + std::string mAddress; + std::size_t mSize; + U32 mRefs; + }; + } +} + +U8 const* LLFontManager::loadFont( std::string const &aFilename, long &a_Size) +{ + a_Size = 0; + std::map< std::string, std::shared_ptr >::iterator itr = m_LoadedFonts.find( aFilename ); + if( itr != m_LoadedFonts.end() ) + { + ++itr->second->mRefs; + // A possible overflow cannot happen here, as it is asserted that the size is less than std::numeric_limits::max() a few lines below. + a_Size = static_cast(itr->second->mSize); + return reinterpret_cast(itr->second->mAddress.c_str()); + } + + auto strContent = LLFile::getContents(aFilename); + + if( strContent.empty() ) + return nullptr; + + // For fontconfig a type of long is required, std::string::size() returns size_t. I think it is safe to limit this to 2GiB and not support fonts that huge (can that even be a thing?) + llassert_always( strContent.size() < std::numeric_limits::max() ); + + a_Size = static_cast(strContent.size()); + + auto pCache = std::make_shared( aFilename, strContent, a_Size ); + itr = m_LoadedFonts.insert( std::make_pair( aFilename, pCache ) ).first; + + return reinterpret_cast(itr->second->mAddress.c_str()); +} + +void LLFontManager::unloadAllFonts() +{ + m_LoadedFonts.clear(); +} diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h index 1ad795060a..3977911fe5 100644 --- a/indra/llrender/llfontfreetype.h +++ b/indra/llrender/llfontfreetype.h @@ -43,15 +43,28 @@ typedef struct FT_FaceRec_* LLFT_Face; struct FT_StreamRec_; typedef struct FT_StreamRec_ LLFT_Stream; +namespace ll +{ + namespace fonts + { + class LoadedFont; + } +} + class LLFontManager { public: static void initClass(); static void cleanupClass(); + U8 const *loadFont( std::string const &aFilename, long &a_Size ); + private: LLFontManager(); ~LLFontManager(); + + void unloadAllFonts(); + std::map< std::string, std::shared_ptr > m_LoadedFonts; }; struct LLFontGlyphInfo @@ -90,11 +103,6 @@ public: S32 getNumFaces(const std::string& filename); -#ifdef LL_WINDOWS - S32 ftOpenFace(const std::string& filename, S32 face_n); - void clearFontStreams(); -#endif - typedef std::function char_functor_t; void addFallbackFont(const LLPointer& fallback_font, const char_functor_t& functor = nullptr); @@ -170,11 +178,6 @@ private: LLFT_Face mFTFace; -#ifdef LL_WINDOWS - llifstream *pFileStream; - LLFT_Stream *pFtStream; -#endif - bool mIsFallback; typedef std::pair, char_functor_t> fallback_font_t; typedef std::vector fallback_font_vector_t; -- cgit v1.3 From 36d4dc4e2be8ac6c6d042b0a1e5c130b6544ef7f Mon Sep 17 00:00:00 2001 From: Rye Date: Mon, 3 Feb 2025 11:37:08 -0500 Subject: Fix uninitialized variable warnings being emitted by current clang --- indra/llmessage/llxfermanager.cpp | 2 +- indra/llrender/llgl.cpp | 13 +------------ indra/llxml/llxmlnode.cpp | 6 +++--- indra/newview/llpanelprimmediacontrols.cpp | 2 +- 4 files changed, 6 insertions(+), 17 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp index f6ed43a4e4..a2d09f4f36 100644 --- a/indra/llmessage/llxfermanager.cpp +++ b/indra/llmessage/llxfermanager.cpp @@ -1051,7 +1051,7 @@ void LLXferManager::retransmitUnackedPackets() // Re-build mOutgoingHosts data updateHostStatus(); - F32 et; + F32 et = 0.f; iter = mSendList.begin(); while (iter != mSendList.end()) { diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 008ee8d450..fbd4b0f9c4 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -1123,17 +1123,6 @@ bool LLGLManager::initGL() if (mGLVersion >= 2.f) { parse_glsl_version(mGLSLVersionMajor, mGLSLVersionMinor); - -#if 0 && LL_DARWIN - // TODO maybe switch to using a core profile for GL 3.2? - // https://stackoverflow.com/a/19868861 - //never use GLSL greater than 1.20 on OSX - if (mGLSLVersionMajor > 1 || mGLSLVersionMinor > 30) - { - mGLSLVersionMajor = 1; - mGLSLVersionMinor = 30; - } -#endif } if (mGLVersion >= 2.1f && LLImageGL::sCompressTextures) @@ -2749,7 +2738,7 @@ void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d) if(cplane[2] < 0) cplane *= -1; - glm::mat4 suffix; + glm::mat4 suffix = glm::identity(); suffix = glm::row(suffix, 2, cplane); glm::mat4 newP = suffix * P; gGL.matrixMode(LLRender::MM_PROJECTION); diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index 92bcb1a2ae..da69e11f87 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -1281,7 +1281,7 @@ bool LLXMLNode::getAttributeU8(const char* name, U8& value ) bool LLXMLNode::getAttributeS8(const char* name, S8& value ) { LLXMLNodePtr node; - S32 val; + S32 val{}; if (!(getAttribute(name, node) && node->getIntValue(1, &val))) { return false; @@ -1293,7 +1293,7 @@ bool LLXMLNode::getAttributeS8(const char* name, S8& value ) bool LLXMLNode::getAttributeU16(const char* name, U16& value ) { LLXMLNodePtr node; - U32 val; + U32 val{}; if (!(getAttribute(name, node) && node->getUnsignedValue(1, &val))) { return false; @@ -1305,7 +1305,7 @@ bool LLXMLNode::getAttributeU16(const char* name, U16& value ) bool LLXMLNode::getAttributeS16(const char* name, S16& value ) { LLXMLNodePtr node; - S32 val; + S32 val{}; if (!(getAttribute(name, node) && node->getIntValue(1, &val))) { return false; diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index b8c12ce0b9..18f8934f9d 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -645,7 +645,7 @@ void LLPanelPrimMediaControls::updateShape() vert_it = vect_face.begin(); vert_end = vect_face.end(); - glm::mat4 mat; + glm::mat4 mat = glm::identity(); if (!is_hud) { mat = get_current_projection() * get_current_modelview(); -- cgit v1.3 From fd94dc0cd0afbca1446945522805dd833d45be7f Mon Sep 17 00:00:00 2001 From: Rye Date: Mon, 10 Feb 2025 14:10:47 -0500 Subject: Disable old GPU hacks on macos when running against Apple GPU --- indra/llrender/llglslshader.cpp | 7 +++++-- indra/llrender/llshadermgr.cpp | 2 +- indra/llrender/llvertexbuffer.cpp | 6 ------ indra/newview/pipeline.cpp | 9 ++++++--- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 0841c0e943..66f38c9281 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -421,8 +421,11 @@ bool LLGLSLShader::createShader() llassert_always(!mShaderFiles.empty()); #if LL_DARWIN - // work-around missing mix(vec3,vec3,bvec3) - mDefines["OLD_SELECT"] = "1"; + if(!gGLManager.mIsApple) + { + // work-around missing mix(vec3,vec3,bvec3) + mDefines["OLD_SELECT"] = "1"; + } #endif mShaderHash = hash(); diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 25d8ccd4b3..b1e2114156 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -450,7 +450,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev // endsure work-around for missing GLSL funcs gets propogated to feature shader files (e.g. srgbF.glsl) #if LL_DARWIN - if (defines) + if (!gGLManager.mIsApple && defines) { (*defines)["OLD_SELECT"] = "1"; } diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 86ec9a453b..d59ddd0fec 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -787,12 +787,6 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto gGL.syncMatrices(); - U32 mask = LLVertexBuffer::MAP_VERTEX; - if (tc) - { - mask = mask | LLVertexBuffer::MAP_TEXCOORD0; - } - unbind(); gGL.begin(mode); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index ddfb5a5621..4a4b938152 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1440,9 +1440,12 @@ void LLPipeline::createLUTBuffers() 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; + if(!gGLManager.mIsApple) + { + // 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); -- cgit v1.3 From 0f4aa87caca779d77c19dfef06fe8a276f7d0eb6 Mon Sep 17 00:00:00 2001 From: Rye Date: Mon, 10 Feb 2025 16:11:39 -0500 Subject: Vectorize LLRender UI scale and offset stack to resolve perf hotspot on arm --- indra/llrender/llrender.cpp | 53 +++++++++++++++------------------------------ indra/llrender/llrender.h | 9 +++----- 2 files changed, 21 insertions(+), 41 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index ec76aa4f36..c26e9b15b8 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -118,7 +118,7 @@ static const GLenum sGLBlendFactor[] = LLTexUnit::LLTexUnit(S32 index) : mCurrTexType(TT_NONE), - mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0), + mCurrTexture(0), mHasMipMaps(false), mIndex(index) { @@ -600,26 +600,6 @@ GLint LLTexUnit::getTextureSourceType(eTextureBlendSrc src, bool isAlpha) } } -void LLTexUnit::setColorScale(S32 scale) -{ - if (mCurrColorScale != scale || gGL.mDirty) - { - mCurrColorScale = scale; - gGL.flush(); - glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, scale ); - } -} - -void LLTexUnit::setAlphaScale(S32 scale) -{ - if (mCurrAlphaScale != scale || gGL.mDirty) - { - mCurrAlphaScale = scale; - gGL.flush(); - glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale ); - } -} - // Useful for debugging that you've manually assigned a texture operation to the correct // texture unit based on the currently set active texture in opengl. void LLTexUnit::debugTextureUnit(void) @@ -1283,9 +1263,7 @@ void LLRender::translateUI(F32 x, F32 y, F32 z) LL_ERRS() << "Need to push a UI translation frame before offsetting" << LL_ENDL; } - mUIOffset.back().mV[0] += x; - mUIOffset.back().mV[1] += y; - mUIOffset.back().mV[2] += z; + mUIOffset.back().add(LLVector4a(x, y, z)); } void LLRender::scaleUI(F32 x, F32 y, F32 z) @@ -1295,14 +1273,14 @@ void LLRender::scaleUI(F32 x, F32 y, F32 z) LL_ERRS() << "Need to push a UI transformation frame before scaling." << LL_ENDL; } - mUIScale.back().scaleVec(LLVector3(x,y,z)); + mUIScale.back().mul(LLVector4a(x, y, z)); } void LLRender::pushUIMatrix() { if (mUIOffset.empty()) { - mUIOffset.emplace_back(0.f,0.f,0.f); + mUIOffset.emplace_back(0.f); } else { @@ -1311,7 +1289,7 @@ void LLRender::pushUIMatrix() if (mUIScale.empty()) { - mUIScale.emplace_back(1.f,1.f,1.f); + mUIScale.emplace_back(1.f); } else { @@ -1333,18 +1311,20 @@ LLVector3 LLRender::getUITranslation() { if (mUIOffset.empty()) { - return LLVector3(0,0,0); + return LLVector3::zero; } - return mUIOffset.back(); + + return LLVector3(mUIOffset.back().getF32ptr()); } LLVector3 LLRender::getUIScale() { if (mUIScale.empty()) { - return LLVector3(1,1,1); + return LLVector3::all_one; } - return mUIScale.back(); + + return LLVector3(mUIScale.back().getF32ptr()); } @@ -1354,8 +1334,9 @@ void LLRender::loadUIIdentity() { LL_ERRS() << "Need to push UI translation frame before clearing offset." << LL_ENDL; } - mUIOffset.back().setVec(0,0,0); - mUIScale.back().setVec(1,1,1); + + mUIOffset.back().clear(); + mUIScale.back().splat(1); } void LLRender::setColorMask(bool writeColor, bool writeAlpha) @@ -1783,8 +1764,10 @@ void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) } else { - LLVector3 vert = (LLVector3(x,y,z)+mUIOffset.back()).scaledVec(mUIScale.back()); - mVerticesp[mCount].set(vert.mV[VX], vert.mV[VY], vert.mV[VZ]); + LLVector4a vert(x, y, z); + vert.add(mUIOffset.back()); + vert.mul(mUIScale.back()); + mVerticesp[mCount] = vert; } mCount++; diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 7b6bd4198b..9e68c2dcd1 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -43,6 +43,7 @@ #include "llglheaders.h" #include "llmatrix4a.h" #include "glm/mat4x4.hpp" +#include #include #include @@ -227,13 +228,9 @@ protected: S32 mIndex; U32 mCurrTexture; eTextureType mCurrTexType; - S32 mCurrColorScale; - S32 mCurrAlphaScale; bool mHasMipMaps; void debugTextureUnit(void); - void setColorScale(S32 scale); - void setAlphaScale(S32 scale); GLint getTextureSource(eTextureBlendSrc src); GLint getTextureSourceType(eTextureBlendSrc src, bool isAlpha = false); }; @@ -526,8 +523,8 @@ private: eBlendFactor mCurrBlendAlphaSFactor; eBlendFactor mCurrBlendAlphaDFactor; - std::vector mUIOffset; - std::vector mUIScale; + std::vector > mUIOffset; + std::vector > mUIScale; }; extern F32 gGLModelView[16]; -- cgit v1.3 From f40c5b209b48b6dd1f8e345598104691ce6c932c Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Wed, 26 Feb 2025 23:05:09 +0200 Subject: #3597 Fix crash when RenderDebugGLSession is True --- indra/llrender/llgl.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 1bc5e79835..1966e48f2e 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -2458,12 +2458,15 @@ void LLGLState::checkStates(GLboolean writeAlpha) return; } - GLint src; - GLint dst; - glGetIntegerv(GL_BLEND_SRC, &src); - glGetIntegerv(GL_BLEND_DST, &dst); - llassert_always(src == GL_SRC_ALPHA); - llassert_always(dst == GL_ONE_MINUS_SRC_ALPHA); + GLint srcRGB, dstRGB, srcAlpha, dstAlpha; + glGetIntegerv(GL_BLEND_SRC_RGB, &srcRGB); + glGetIntegerv(GL_BLEND_DST_RGB, &dstRGB); + glGetIntegerv(GL_BLEND_SRC_ALPHA, &srcAlpha); + glGetIntegerv(GL_BLEND_DST_ALPHA, &dstAlpha); + llassert_always(srcRGB == GL_SRC_ALPHA); + llassert_always(srcAlpha == GL_SRC_ALPHA); + llassert_always(dstRGB == GL_ONE_MINUS_SRC_ALPHA); + llassert_always(dstAlpha == GL_ONE_MINUS_SRC_ALPHA); // disable for now until usage is consistent //GLboolean colorMask[4]; -- cgit v1.3 From 44fa0c438ae36528b812237488dcbf51f10708e0 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 7 Mar 2025 22:38:17 +0200 Subject: #3696 LLFontFreetype crash when adding glyph --- indra/llrender/llfontfreetype.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 62b551f1e0..649dd369cb 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -725,11 +725,11 @@ void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index, ll || FT_Err_Invalid_Composite == error || (FT_Err_Ok != error && LLStringOps::isEmoji(wch))) { - glyph_index = FT_Get_Char_Index(mFTFace, '?'); - // if '?' is not present, potentially can use last index, that's supposed to be null glyph - if (glyph_index > 0) + // value~0 always corresponds to the 'missing glyph' + error = FT_Load_Glyph(mFTFace, 0, FT_LOAD_FORCE_AUTOHINT); + if (FT_Err_Ok != error) { - error = FT_Load_Glyph(mFTFace, glyph_index, load_flags ^ FT_LOAD_COLOR); + LL_ERRS() << "Loading fallback for char '" << (U32)wch << "', glyph " << glyph_index << " failed with error : " << (S32)error << LL_ENDL; } } llassert_always_msg(FT_Err_Ok == error, message.c_str()); -- cgit v1.3 From 5e5d466628f3576bb48b63f143502ea914f79bca Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 24 Mar 2025 17:59:13 -0400 Subject: Readd probe count setting (#3793) * Readd max probe count. Disable dynamic probe allocation by default (for now). --- indra/llrender/llcubemaparray.cpp | 32 ++++++++ indra/llrender/llcubemaparray.h | 2 + indra/newview/app_settings/settings.xml | 11 +++ .../shaders/class3/environment/waterF.glsl | 3 +- indra/newview/featuretable.txt | 10 +++ indra/newview/featuretable_mac.txt | 10 +++ indra/newview/llreflectionmapmanager.cpp | 90 +++++++++++++--------- .../en/floater_preferences_graphics_advanced.xml | 45 +++++++++++ 8 files changed, 165 insertions(+), 38 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp index d0a97dc2c6..998b57217d 100644 --- a/indra/llrender/llcubemaparray.cpp +++ b/indra/llrender/llcubemaparray.cpp @@ -105,6 +105,36 @@ LLCubeMapArray::LLCubeMapArray() } +LLCubeMapArray::LLCubeMapArray(LLCubeMapArray& lhs, U32 width, U32 count) : mTextureStage(0) +{ + mWidth = width; + mCount = count; + + // Allocate a new cubemap array with the same criteria as the incoming cubemap array + allocate(mWidth, lhs.mImage->getComponents(), count, lhs.mImage->getUseMipMaps(), lhs.mHDR); + + // Copy each cubemap from the incoming array to the new array + U32 min_count = std::min(count, lhs.mCount); + for (U32 i = 0; i < min_count * 6; ++i) + { + U32 src_resolution = lhs.mWidth; + U32 dst_resolution = mWidth; + { + GLint components = GL_RGB; + if (mImage->getComponents() == 4) + components = GL_RGBA; + GLint format = GL_RGB; + + // Handle different resolutions by scaling the image + LLPointer src_image = new LLImageRaw(lhs.mWidth, lhs.mWidth, lhs.mImage->getComponents()); + glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, components, GL_UNSIGNED_BYTE, src_image->getData()); + + LLPointer scaled_image = src_image->scaled(mWidth, mWidth); + glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, i, mWidth, mWidth, 1, components, GL_UNSIGNED_BYTE, scaled_image->getData()); + } + } +} + LLCubeMapArray::~LLCubeMapArray() { } @@ -115,6 +145,8 @@ void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, bool us mWidth = resolution; mCount = count; + mHDR = hdr; + LLImageGL::generateTextures(1, &texname); mImage = new LLImageGL(resolution, resolution, components, use_mips); diff --git a/indra/llrender/llcubemaparray.h b/indra/llrender/llcubemaparray.h index bfc72a321d..6b4288cb23 100644 --- a/indra/llrender/llcubemaparray.h +++ b/indra/llrender/llcubemaparray.h @@ -36,6 +36,7 @@ class LLCubeMapArray : public LLRefCount { public: LLCubeMapArray(); + LLCubeMapArray(LLCubeMapArray& lhs, U32 width, U32 count); static GLenum sTargets[6]; @@ -73,4 +74,5 @@ protected: U32 mWidth = 0; U32 mCount = 0; S32 mTextureStage; + bool mHDR; }; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4ce7e0f729..b7127adc53 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9087,6 +9087,17 @@ Value 1 + RenderReflectionProbeDynamicAllocation + + Comment + Enable dynamic allocation of reflection probes. -1 means no dynamic allocation. Sets a buffer to allocate when a dynamic allocation occurs otherwise. + Persist + 1 + Type + S32 + Value + -1 + RenderReflectionProbeCount Comment diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl index 1b7b0c1937..e57aa69731 100644 --- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl @@ -26,6 +26,7 @@ // class3/environment/waterF.glsl #define WATER_MINIMAL 1 +#define SHORELINE_FADE 1 out vec4 frag_color; @@ -264,7 +265,7 @@ void main() // Calculate some distance fade in the water to better assist with refraction blending and reducing the refraction texture's "disconnect". #ifdef SHORELINE_FADE - fade = max(0,min(1, (pos.z - refPos.z) / 10)) + fade = max(0,min(1, (pos.z - refPos.z) / 10)); #else fade = 1 * water_mask; #endif diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 443a7ae914..c0009d24ee 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -86,6 +86,7 @@ RenderTonemapType 1 1 RenderTonemapMix 1 1 RenderDisableVintageMode 1 1 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 256 // // Low Graphics Settings @@ -128,6 +129,7 @@ RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 512 +RenderReflectionProbeCount 1 1 // // Medium Low Graphics Settings @@ -170,6 +172,7 @@ RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 1024 +RenderReflectionProbeCount 1 32 // // Medium Graphics Settings (standard) @@ -211,6 +214,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 64 // // Medium High Graphics Settings @@ -252,6 +256,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 64 // // High Graphics Settings (SSAO + sun shadows) @@ -293,6 +298,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 128 // // High Ultra Graphics Settings (deferred + SSAO + all shadows) @@ -334,6 +340,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 256 // // Ultra graphics (REALLY PURTY!) @@ -375,6 +382,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 256 // // Class Unknown Hardware (unknown) @@ -408,6 +416,7 @@ RenderReflectionProbeDetail 0 -1 RenderMirrors 0 0 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 0 0 list Intel RenderAnisotropic 1 0 @@ -429,6 +438,7 @@ RenderMirrors 0 0 RenderGLMultiThreadedTextures 0 0 RenderGLMultiThreadedMedia 0 0 RenderDisableVintageMode 1 0 +RenderReflectionProbeCount 0 0 list TexUnit16orLess RenderTerrainPBRDetail 1 -1 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index dc9473b042..5940d1ec12 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -86,6 +86,7 @@ RenderTonemapMix 1 1 RenderDisableVintageMode 1 1 RenderDownScaleMethod 1 0 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 256 // // Low Graphics Settings @@ -128,6 +129,7 @@ RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 512 +RenderReflectionProbeCount 1 1 // // Medium Low Graphics Settings @@ -170,6 +172,7 @@ RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 1024 +RenderReflectionProbeCount 1 32 // // Medium Graphics Settings (standard) @@ -211,6 +214,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 64 // // Medium High Graphics Settings @@ -252,6 +256,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 64 // // High Graphics Settings (SSAO + sun shadows) @@ -293,6 +298,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 128 // // High Ultra Graphics Settings (SSAO + all shadows) @@ -334,6 +340,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 256 // // Ultra graphics (REALLY PURTY!) @@ -375,6 +382,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 256 // // Class Unknown Hardware (unknown) @@ -407,6 +415,7 @@ RenderShadowDetail 0 0 RenderMirrors 0 0 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 0 0 list TexUnit8orLess RenderDeferredSSAO 0 0 @@ -447,6 +456,7 @@ RenderReflectionProbeDetail 0 0 RenderReflectionsEnabled 0 0 RenderMirrors 0 0 RenderDisableVintageMode 1 0 +RenderReflectionProbeCount 0 0 list VaryingVectors16orLess RenderTerrainPBRPlanarSampleCount 1 1 diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 34c6034e9e..f2abc7b8b7 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -224,48 +224,54 @@ void LLReflectionMapManager::update() static LLCachedControl sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1); static LLCachedControl sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3); + static LLCachedControl sReflectionProbeCount(gSavedSettings, "RenderReflectionProbeCount", 256U); + static LLCachedControl sProbeDynamicAllocation(gSavedSettings, "RenderReflectionProbeDynamicAllocation", -1); + mResetFade = llmin((F32)(mResetFade + gFrameIntervalSeconds * 2.f), 1.f); - // Once every 20 frames, update the dynamic probe count. - if (gFrameCount % 20) { U32 probe_count_temp = mDynamicProbeCount; - if (sLevel == 0) - { - mDynamicProbeCount = 1; - } - else if (sLevel == 1) + if (sProbeDynamicAllocation > -1) { - mDynamicProbeCount = (U32)mProbes.size(); + if (sLevel == 0) + { + mDynamicProbeCount = 1; + } + else if (sLevel == 1) + { + mDynamicProbeCount = (U32)mProbes.size(); + } + else if (sLevel == 2) + { + mDynamicProbeCount = llmax((U32)mProbes.size(), 128); + } + else + { + mDynamicProbeCount = 256; + } - } - else if (sLevel == 2) - { - mDynamicProbeCount = llmax((U32)mProbes.size(), 128); + if (sProbeDynamicAllocation > 1) + { + // Round mDynamicProbeCount to the nearest increment of 16 + mDynamicProbeCount = ((mDynamicProbeCount + sProbeDynamicAllocation / 2) / sProbeDynamicAllocation) * 16; + mDynamicProbeCount = llclamp(mDynamicProbeCount, 1, sReflectionProbeCount); + } + else + { + mDynamicProbeCount = llclamp(mDynamicProbeCount + sProbeDynamicAllocation, 1, sReflectionProbeCount); + } } else { - mDynamicProbeCount = 256; + mDynamicProbeCount = sReflectionProbeCount; } - // Round mDynamicProbeCount to the nearest increment of 32 - mDynamicProbeCount = ((mDynamicProbeCount + 16) / 32) * 32; - mDynamicProbeCount = llclamp(mDynamicProbeCount, 1, LL_MAX_REFLECTION_PROBE_COUNT); + mDynamicProbeCount = llmin(mDynamicProbeCount, LL_MAX_REFLECTION_PROBE_COUNT); - if (mDynamicProbeCount < probe_count_temp * 1.1 && mDynamicProbeCount > probe_count_temp * 0.9) - mDynamicProbeCount = probe_count_temp; - else - mGlobalFadeTarget = 0.f; + if (mDynamicProbeCount != probe_count_temp) + mResetFade = 1.f; } - if (mGlobalFadeTarget < mResetFade) - mResetFade = llmax(mGlobalFadeTarget, mResetFade - (F32)gFrameIntervalSeconds * 2); - else - mResetFade = llmin(mGlobalFadeTarget, mResetFade + (F32)gFrameIntervalSeconds * 2); - - if (mResetFade == mGlobalFadeTarget) - { - initReflectionMaps(); - } + initReflectionMaps(); static LLCachedControl render_hdr(gSavedSettings, "RenderHDREnabled", true); @@ -356,6 +362,7 @@ void LLReflectionMapManager::update() probe->mCubeArray = nullptr; probe->mCubeIndex = -1; probe->mComplete = false; + probe->mFadeIn = 0; } } @@ -1418,8 +1425,6 @@ void LLReflectionMapManager::initReflectionMaps() } gEXRImage = nullptr; - mGlobalFadeTarget = 1.f; - mResetFade = -0.125f; mReset = false; mReflectionProbeCount = mDynamicProbeCount; mProbeResolution = probe_resolution; @@ -1429,15 +1434,25 @@ void LLReflectionMapManager::initReflectionMaps() mTexture->getWidth() != mProbeResolution || mReflectionProbeCount + 2 != mTexture->getCount()) { - mTexture = new LLCubeMapArray(); + if (mTexture) + { + mTexture = new LLCubeMapArray(*mTexture, mProbeResolution, mReflectionProbeCount + 2); - static LLCachedControl render_hdr(gSavedSettings, "RenderHDREnabled", true); + mIrradianceMaps = new LLCubeMapArray(*mIrradianceMaps, LL_IRRADIANCE_MAP_RESOLUTION, mReflectionProbeCount); + } + else + { + mTexture = new LLCubeMapArray(); + + static LLCachedControl render_hdr(gSavedSettings, "RenderHDREnabled", true); - // store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation source) - mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2, true, render_hdr); + // store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation + // source) + mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2, true, render_hdr); - mIrradianceMaps = new LLCubeMapArray(); - mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, false, render_hdr); + mIrradianceMaps = new LLCubeMapArray(); + mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, false, render_hdr); + } } // reset probe state @@ -1457,6 +1472,7 @@ void LLReflectionMapManager::initReflectionMaps() probe->mCubeArray = nullptr; probe->mCubeIndex = -1; probe->mNeighbors.clear(); + probe->mFadeIn = 0; } mCubeFree.clear(); 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 78d13293a8..6877ce6411 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 @@ -858,6 +858,51 @@ value="3"/> + + Max Reflection Probes: + + + + + + + + + + Date: Wed, 2 Apr 2025 01:50:21 +0300 Subject: #3597 Improve error handling at LLGLSLShader::disableTexture() --- indra/llrender/llglslshader.cpp | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index b3f32fdc83..50e40a3eb6 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -1247,23 +1247,40 @@ S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode) llassert(false); return -1; } + S32 index = mTexture[uniform]; - if (index != -1 && gGL.getTexUnit(index)->getCurrType() != LLTexUnit::TT_NONE) + if (index < 0) + { + // Invalid texture index - nothing to disable + return index; + } + + LLTexUnit* tex_unit = gGL.getTexUnit(index); + if (!tex_unit) { - if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode) + // Invalid texture unit + LL_WARNS_ONCE("Shader") << "Invalid texture unit at index: " << index << LL_ENDL; + return index; + } + + LLTexUnit::eTextureType curr_type = tex_unit->getCurrType(); + if (curr_type != LLTexUnit::TT_NONE) + { + if (gDebugGL && curr_type != mode) { if (gDebugSession) { - gFailLog << "Texture channel " << index << " texture type corrupted." << std::endl; + gFailLog << "Texture channel " << index << " texture type corrupted. Expected: " << mode << ", Found: " << curr_type << std::endl; ll_fail("LLGLSLShader::disableTexture failed"); } else { - LL_ERRS() << "Texture channel " << index << " texture type corrupted." << LL_ENDL; + LL_ERRS() << "Texture channel " << index << " texture type corrupted. Expected: " << mode << ", Found: " << curr_type << LL_ENDL; } } - gGL.getTexUnit(index)->disable(); + tex_unit->disable(); } + return index; } -- cgit v1.3 From 2da46c38305f6002993cd1974a9342935e97f8c6 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 1 Apr 2025 22:59:22 +0300 Subject: #3575 Clean up obsolete VRAM detectin logic --- indra/llrender/llgl.cpp | 19 - indra/llwindow/lldxhardware.cpp | 652 ------------------------- indra/llwindow/lldxhardware.h | 68 --- indra/newview/llappviewerwin32.cpp | 60 +-- indra/newview/skins/default/xui/en/strings.xml | 1 - 5 files changed, 1 insertion(+), 799 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 1966e48f2e..0be27b8975 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -1228,28 +1228,9 @@ bool LLGLManager::initGL() } #endif -#if LL_WINDOWS - if (mVRAM < 256) - { - // Something likely went wrong using the above extensions - // try WMI first and fall back to old method (from dxdiag) if all else fails - // Function will check all GPUs WMI knows of and will pick up the one with most - // memory. We need to check all GPUs because system can switch active GPU to - // weaker one, to preserve power when not under load. - U32 mem = LLDXHardware::getMBVideoMemoryViaWMI(); - if (mem != 0) - { - mVRAM = mem; - LL_WARNS("RenderInit") << "VRAM Detected (WMI):" << mVRAM<< LL_ENDL; - } - } -#endif - if (mVRAM < 256 && old_vram > 0) { // fall back to old method - // Note: on Windows value will be from LLDXHardware. - // Either received via dxdiag or via WMI by id from dxdiag. mVRAM = old_vram; } diff --git a/indra/llwindow/lldxhardware.cpp b/indra/llwindow/lldxhardware.cpp index 4bc069c5a4..387982dfc2 100644 --- a/indra/llwindow/lldxhardware.cpp +++ b/indra/llwindow/lldxhardware.cpp @@ -47,7 +47,6 @@ #include "llstl.h" #include "lltimer.h" -void (*gWriteDebug)(const char* msg) = NULL; LLDXHardware gDXHardware; //----------------------------------------------------------------------------- @@ -61,170 +60,6 @@ typedef BOOL ( WINAPI* PfnCoSetProxyBlanket )( IUnknown* pProxy, DWORD dwAuthnSv OLECHAR* pServerPrincName, DWORD dwAuthnLevel, DWORD dwImpLevel, RPC_AUTH_IDENTITY_HANDLE pAuthInfo, DWORD dwCapabilities ); -HRESULT GetVideoMemoryViaWMI(WCHAR* strInputDeviceID, DWORD* pdwAdapterRam) -{ - HRESULT hr; - bool bGotMemory = false; - IWbemLocator* pIWbemLocator = nullptr; - IWbemServices* pIWbemServices = nullptr; - BSTR pNamespace = nullptr; - - *pdwAdapterRam = 0; - CoInitializeEx(0, COINIT_APARTMENTTHREADED); - - hr = CoCreateInstance( CLSID_WbemLocator, - nullptr, - CLSCTX_INPROC_SERVER, - IID_IWbemLocator, - ( LPVOID* )&pIWbemLocator ); -#ifdef PRINTF_DEBUGGING - if( FAILED( hr ) ) wprintf( L"WMI: CoCreateInstance failed: 0x%0.8x\n", hr ); -#endif - - if( SUCCEEDED( hr ) && pIWbemLocator ) - { - // Using the locator, connect to WMI in the given namespace. - pNamespace = SysAllocString( L"\\\\.\\root\\cimv2" ); - - hr = pIWbemLocator->ConnectServer( pNamespace, nullptr, nullptr, 0L, - 0L, nullptr, nullptr, &pIWbemServices ); -#ifdef PRINTF_DEBUGGING - if( FAILED( hr ) ) wprintf( L"WMI: pIWbemLocator->ConnectServer failed: 0x%0.8x\n", hr ); -#endif - if( SUCCEEDED( hr ) && pIWbemServices != 0 ) - { - HINSTANCE hinstOle32 = nullptr; - - hinstOle32 = LoadLibraryW( L"ole32.dll" ); - if( hinstOle32 ) - { - PfnCoSetProxyBlanket pfnCoSetProxyBlanket = nullptr; - - pfnCoSetProxyBlanket = ( PfnCoSetProxyBlanket )GetProcAddress( hinstOle32, "CoSetProxyBlanket" ); - if( pfnCoSetProxyBlanket != 0 ) - { - // Switch security level to IMPERSONATE. - pfnCoSetProxyBlanket( pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr, - RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, 0 ); - } - - FreeLibrary( hinstOle32 ); - } - - IEnumWbemClassObject* pEnumVideoControllers = nullptr; - BSTR pClassName = nullptr; - - pClassName = SysAllocString( L"Win32_VideoController" ); - - hr = pIWbemServices->CreateInstanceEnum( pClassName, 0, - nullptr, &pEnumVideoControllers ); -#ifdef PRINTF_DEBUGGING - if( FAILED( hr ) ) wprintf( L"WMI: pIWbemServices->CreateInstanceEnum failed: 0x%0.8x\n", hr ); -#endif - - if( SUCCEEDED( hr ) && pEnumVideoControllers ) - { - IWbemClassObject* pVideoControllers[10] = {0}; - DWORD uReturned = 0; - BSTR pPropName = nullptr; - - // Get the first one in the list - pEnumVideoControllers->Reset(); - hr = pEnumVideoControllers->Next( 5000, // timeout in 5 seconds - 10, // return the first 10 - pVideoControllers, - &uReturned ); -#ifdef PRINTF_DEBUGGING - if( FAILED( hr ) ) wprintf( L"WMI: pEnumVideoControllers->Next failed: 0x%0.8x\n", hr ); - if( uReturned == 0 ) wprintf( L"WMI: pEnumVideoControllers uReturned == 0\n" ); -#endif - - VARIANT var; - if( SUCCEEDED( hr ) ) - { - bool bFound = false; - for( UINT iController = 0; iController < uReturned; iController++ ) - { - if ( !pVideoControllers[iController] ) - continue; - - // if strInputDeviceID is set find this specific device and return memory or specific device - // if strInputDeviceID is not set return the best device - if (strInputDeviceID) - { - pPropName = SysAllocString( L"PNPDeviceID" ); - hr = pVideoControllers[iController]->Get( pPropName, 0L, &var, nullptr, nullptr ); -#ifdef PRINTF_DEBUGGING - if( FAILED( hr ) ) - wprintf( L"WMI: pVideoControllers[iController]->Get PNPDeviceID failed: 0x%0.8x\n", hr ); -#endif - if( SUCCEEDED( hr ) && strInputDeviceID) - { - if( wcsstr( var.bstrVal, strInputDeviceID ) != 0 ) - bFound = true; - } - VariantClear( &var ); - if( pPropName ) SysFreeString( pPropName ); - } - - if( bFound || !strInputDeviceID ) - { - pPropName = SysAllocString( L"AdapterRAM" ); - hr = pVideoControllers[iController]->Get( pPropName, 0L, &var, nullptr, nullptr ); -#ifdef PRINTF_DEBUGGING - if( FAILED( hr ) ) - wprintf( L"WMI: pVideoControllers[iController]->Get AdapterRAM failed: 0x%0.8x\n", - hr ); -#endif - if( SUCCEEDED( hr ) ) - { - bGotMemory = true; - *pdwAdapterRam = llmax(var.ulVal, *pdwAdapterRam); - } - VariantClear( &var ); - if( pPropName ) SysFreeString( pPropName ); - } - - SAFE_RELEASE( pVideoControllers[iController] ); - - if (bFound) - { - break; - } - } - } - } - - if( pClassName ) - SysFreeString( pClassName ); - SAFE_RELEASE( pEnumVideoControllers ); - } - - if( pNamespace ) - SysFreeString( pNamespace ); - SAFE_RELEASE( pIWbemServices ); - } - - SAFE_RELEASE( pIWbemLocator ); - - CoUninitialize(); - - if( bGotMemory ) - return S_OK; - else - return E_FAIL; -} - -//static -U32 LLDXHardware::getMBVideoMemoryViaWMI() -{ - DWORD vram = 0; - if (SUCCEEDED(GetVideoMemoryViaWMI(NULL, &vram))) - { - return vram / (1024 * 1024);; - } - return 0; -} //Getting the version of graphics controller driver via WMI std::string LLDXHardware::getDriverVersionWMI(EGPUVendor vendor) @@ -480,495 +315,14 @@ std::string get_string(IDxDiagContainer *containerp, const WCHAR *wszPropName) return utf16str_to_utf8str(wszPropValue); } - -LLVersion::LLVersion() -{ - mValid = false; - S32 i; - for (i = 0; i < 4; i++) - { - mFields[i] = 0; - } -} - -bool LLVersion::set(const std::string &version_string) -{ - S32 i; - for (i = 0; i < 4; i++) - { - mFields[i] = 0; - } - // Split the version string. - std::string str(version_string); - typedef boost::tokenizer > tokenizer; - boost::char_separator sep(".", "", boost::keep_empty_tokens); - tokenizer tokens(str, sep); - - tokenizer::iterator iter = tokens.begin(); - S32 count = 0; - for (;(iter != tokens.end()) && (count < 4);++iter) - { - mFields[count] = atoi(iter->c_str()); - count++; - } - if (count < 4) - { - //LL_WARNS() << "Potentially bogus version string!" << version_string << LL_ENDL; - for (i = 0; i < 4; i++) - { - mFields[i] = 0; - } - mValid = false; - } - else - { - mValid = true; - } - return mValid; -} - -S32 LLVersion::getField(const S32 field_num) -{ - if (!mValid) - { - return -1; - } - else - { - return mFields[field_num]; - } -} - -std::string LLDXDriverFile::dump() -{ - if (gWriteDebug) - { - gWriteDebug("Filename:"); - gWriteDebug(mName.c_str()); - gWriteDebug("\n"); - gWriteDebug("Ver:"); - gWriteDebug(mVersionString.c_str()); - gWriteDebug("\n"); - gWriteDebug("Date:"); - gWriteDebug(mDateString.c_str()); - gWriteDebug("\n"); - } - LL_INFOS() << mFilepath << LL_ENDL; - LL_INFOS() << mName << LL_ENDL; - LL_INFOS() << mVersionString << LL_ENDL; - LL_INFOS() << mDateString << LL_ENDL; - - return ""; -} - -LLDXDevice::~LLDXDevice() -{ - for_each(mDriverFiles.begin(), mDriverFiles.end(), DeletePairedPointer()); - mDriverFiles.clear(); -} - -std::string LLDXDevice::dump() -{ - if (gWriteDebug) - { - gWriteDebug("StartDevice\n"); - gWriteDebug("DeviceName:"); - gWriteDebug(mName.c_str()); - gWriteDebug("\n"); - gWriteDebug("PCIString:"); - gWriteDebug(mPCIString.c_str()); - gWriteDebug("\n"); - } - LL_INFOS() << LL_ENDL; - LL_INFOS() << "DeviceName:" << mName << LL_ENDL; - LL_INFOS() << "PCIString:" << mPCIString << LL_ENDL; - LL_INFOS() << "Drivers" << LL_ENDL; - LL_INFOS() << "-------" << LL_ENDL; - for (driver_file_map_t::iterator iter = mDriverFiles.begin(), - end = mDriverFiles.end(); - iter != end; iter++) - { - LLDXDriverFile *filep = iter->second; - filep->dump(); - } - if (gWriteDebug) - { - gWriteDebug("EndDevice\n"); - } - - return ""; -} - -LLDXDriverFile *LLDXDevice::findDriver(const std::string &driver) -{ - for (driver_file_map_t::iterator iter = mDriverFiles.begin(), - end = mDriverFiles.end(); - iter != end; iter++) - { - LLDXDriverFile *filep = iter->second; - if (!utf8str_compare_insensitive(filep->mName,driver)) - { - return filep; - } - } - - return NULL; -} - LLDXHardware::LLDXHardware() { - mVRAM = 0; - gWriteDebug = NULL; } void LLDXHardware::cleanup() { - // for_each(mDevices.begin(), mDevices.end(), DeletePairedPointer()); - // mDevices.clear(); -} - -/* -std::string LLDXHardware::dumpDevices() -{ - if (gWriteDebug) - { - gWriteDebug("\n"); - gWriteDebug("StartAllDevices\n"); - } - for (device_map_t::iterator iter = mDevices.begin(), - end = mDevices.end(); - iter != end; iter++) - { - LLDXDevice *devicep = iter->second; - devicep->dump(); - } - if (gWriteDebug) - { - gWriteDebug("EndAllDevices\n\n"); - } - return ""; } -LLDXDevice *LLDXHardware::findDevice(const std::string &vendor, const std::string &devices) -{ - // Iterate through different devices tokenized in devices string - std::string str(devices); - typedef boost::tokenizer > tokenizer; - boost::char_separator sep("|", "", boost::keep_empty_tokens); - tokenizer tokens(str, sep); - - tokenizer::iterator iter = tokens.begin(); - for (;iter != tokens.end();++iter) - { - std::string dev_str = *iter; - for (device_map_t::iterator iter = mDevices.begin(), - end = mDevices.end(); - iter != end; iter++) - { - LLDXDevice *devicep = iter->second; - if ((devicep->mVendorID == vendor) - && (devicep->mDeviceID == dev_str)) - { - return devicep; - } - } - } - - return NULL; -} -*/ - -bool LLDXHardware::getInfo(bool vram_only) -{ - LLTimer hw_timer; - bool ok = false; - HRESULT hr; - - // CLSID_DxDiagProvider does not work with Multithreaded? - CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); - - IDxDiagProvider *dx_diag_providerp = NULL; - IDxDiagContainer *dx_diag_rootp = NULL; - IDxDiagContainer *devices_containerp = NULL; - // IDxDiagContainer *system_device_containerp= NULL; - IDxDiagContainer *device_containerp = NULL; - IDxDiagContainer *file_containerp = NULL; - IDxDiagContainer *driver_containerp = NULL; - DWORD dw_device_count; - - mVRAM = 0; - - // CoCreate a IDxDiagProvider* - LL_DEBUGS("AppInit") << "CoCreateInstance IID_IDxDiagProvider" << LL_ENDL; - hr = CoCreateInstance(CLSID_DxDiagProvider, - NULL, - CLSCTX_INPROC_SERVER, - IID_IDxDiagProvider, - (LPVOID*) &dx_diag_providerp); - - if (FAILED(hr)) - { - LL_WARNS("AppInit") << "No DXDiag provider found! DirectX 9 not installed!" << LL_ENDL; - gWriteDebug("No DXDiag provider found! DirectX 9 not installed!\n"); - goto LCleanup; - } - if (SUCCEEDED(hr)) // if FAILED(hr) then dx9 is not installed - { - // Fill out a DXDIAG_INIT_PARAMS struct and pass it to IDxDiagContainer::Initialize - // Passing in TRUE for bAllowWHQLChecks, allows dxdiag to check if drivers are - // digital signed as logo'd by WHQL which may connect via internet to update - // WHQL certificates. - DXDIAG_INIT_PARAMS dx_diag_init_params; - ZeroMemory(&dx_diag_init_params, sizeof(DXDIAG_INIT_PARAMS)); - - dx_diag_init_params.dwSize = sizeof(DXDIAG_INIT_PARAMS); - dx_diag_init_params.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION; - dx_diag_init_params.bAllowWHQLChecks = TRUE; - dx_diag_init_params.pReserved = NULL; - - LL_DEBUGS("AppInit") << "dx_diag_providerp->Initialize" << LL_ENDL; - hr = dx_diag_providerp->Initialize(&dx_diag_init_params); - if(FAILED(hr)) - { - goto LCleanup; - } - - LL_DEBUGS("AppInit") << "dx_diag_providerp->GetRootContainer" << LL_ENDL; - hr = dx_diag_providerp->GetRootContainer( &dx_diag_rootp ); - if(FAILED(hr) || !dx_diag_rootp) - { - goto LCleanup; - } - - HRESULT hr; - - // Get display driver information - LL_DEBUGS("AppInit") << "dx_diag_rootp->GetChildContainer" << LL_ENDL; - hr = dx_diag_rootp->GetChildContainer(L"DxDiag_DisplayDevices", &devices_containerp); - if(FAILED(hr) || !devices_containerp) - { - // do not release 'dirty' devices_containerp at this stage, only dx_diag_rootp - devices_containerp = NULL; - goto LCleanup; - } - - // make sure there is something inside - hr = devices_containerp->GetNumberOfChildContainers(&dw_device_count); - if (FAILED(hr) || dw_device_count == 0) - { - goto LCleanup; - } - - // Get device 0 - // By default 0 device is the primary one, howhever in case of various hybrid graphics - // like itegrated AMD and PCI AMD GPUs system might switch. - LL_DEBUGS("AppInit") << "devices_containerp->GetChildContainer" << LL_ENDL; - hr = devices_containerp->GetChildContainer(L"0", &device_containerp); - if(FAILED(hr) || !device_containerp) - { - goto LCleanup; - } - - DWORD vram = 0; - - WCHAR deviceID[512]; - - get_wstring(device_containerp, L"szDeviceID", deviceID, 512); - // Example: searches id like 1F06 in pnp string (aka VEN_10DE&DEV_1F06) - // doesn't seem to work on some systems since format is unrecognizable - // but in such case keyDeviceID works - if (SUCCEEDED(GetVideoMemoryViaWMI(deviceID, &vram))) - { - mVRAM = vram/(1024*1024); - } - else - { - get_wstring(device_containerp, L"szKeyDeviceID", deviceID, 512); - LL_WARNS() << "szDeviceID" << deviceID << LL_ENDL; - // '+9' to avoid ENUM\\PCI\\ prefix - // Returns string like Enum\\PCI\\VEN_10DE&DEV_1F06&SUBSYS... - // and since GetVideoMemoryViaWMI searches by PNPDeviceID it is sufficient - if (SUCCEEDED(GetVideoMemoryViaWMI(deviceID + 9, &vram))) - { - mVRAM = vram / (1024 * 1024); - } - } - - if (mVRAM == 0) - { // Get the English VRAM string - std::string ram_str = get_string(device_containerp, L"szDisplayMemoryEnglish"); - - // We don't need the device any more - SAFE_RELEASE(device_containerp); - - // Dump the string as an int into the structure - char *stopstring; - mVRAM = strtol(ram_str.c_str(), &stopstring, 10); - LL_INFOS("AppInit") << "VRAM Detected: " << mVRAM << " DX9 string: " << ram_str << LL_ENDL; - } - - if (vram_only) - { - ok = true; - goto LCleanup; - } - - - /* for now, we ONLY do vram_only the rest of this - is commented out, to ensure no-one is tempted - to use it - - // Now let's get device and driver information - // Get the IDxDiagContainer object called "DxDiag_SystemDevices". - // This call may take some time while dxdiag gathers the info. - DWORD num_devices = 0; - WCHAR wszContainer[256]; - LL_DEBUGS("AppInit") << "dx_diag_rootp->GetChildContainer DxDiag_SystemDevices" << LL_ENDL; - hr = dx_diag_rootp->GetChildContainer(L"DxDiag_SystemDevices", &system_device_containerp); - if (FAILED(hr)) - { - goto LCleanup; - } - - hr = system_device_containerp->GetNumberOfChildContainers(&num_devices); - if (FAILED(hr)) - { - goto LCleanup; - } - - LL_DEBUGS("AppInit") << "DX9 iterating over devices" << LL_ENDL; - S32 device_num = 0; - for (device_num = 0; device_num < (S32)num_devices; device_num++) - { - hr = system_device_containerp->EnumChildContainerNames(device_num, wszContainer, 256); - if (FAILED(hr)) - { - goto LCleanup; - } - - hr = system_device_containerp->GetChildContainer(wszContainer, &device_containerp); - if (FAILED(hr) || device_containerp == NULL) - { - goto LCleanup; - } - - std::string device_name = get_string(device_containerp, L"szDescription"); - - std::string device_id = get_string(device_containerp, L"szDeviceID"); - - LLDXDevice *dxdevicep = new LLDXDevice; - dxdevicep->mName = device_name; - dxdevicep->mPCIString = device_id; - mDevices[dxdevicep->mPCIString] = dxdevicep; - - // Split the PCI string based on vendor, device, subsys, rev. - std::string str(device_id); - typedef boost::tokenizer > tokenizer; - boost::char_separator sep("&\\", "", boost::keep_empty_tokens); - tokenizer tokens(str, sep); - - tokenizer::iterator iter = tokens.begin(); - S32 count = 0; - bool valid = true; - for (;(iter != tokens.end()) && (count < 3);++iter) - { - switch (count) - { - case 0: - if (strcmp(iter->c_str(), "PCI")) - { - valid = false; - } - break; - case 1: - dxdevicep->mVendorID = iter->c_str(); - break; - case 2: - dxdevicep->mDeviceID = iter->c_str(); - break; - default: - // Ignore it - break; - } - count++; - } - - - - - // Now, iterate through the related drivers - hr = device_containerp->GetChildContainer(L"Drivers", &driver_containerp); - if (FAILED(hr) || !driver_containerp) - { - goto LCleanup; - } - - DWORD num_files = 0; - hr = driver_containerp->GetNumberOfChildContainers(&num_files); - if (FAILED(hr)) - { - goto LCleanup; - } - - S32 file_num = 0; - for (file_num = 0; file_num < (S32)num_files; file_num++ ) - { - - hr = driver_containerp->EnumChildContainerNames(file_num, wszContainer, 256); - if (FAILED(hr)) - { - goto LCleanup; - } - - hr = driver_containerp->GetChildContainer(wszContainer, &file_containerp); - if (FAILED(hr) || file_containerp == NULL) - { - goto LCleanup; - } - - std::string driver_path = get_string(file_containerp, L"szPath"); - std::string driver_name = get_string(file_containerp, L"szName"); - std::string driver_version = get_string(file_containerp, L"szVersion"); - std::string driver_date = get_string(file_containerp, L"szDatestampEnglish"); - - LLDXDriverFile *dxdriverfilep = new LLDXDriverFile; - dxdriverfilep->mName = driver_name; - dxdriverfilep->mFilepath= driver_path; - dxdriverfilep->mVersionString = driver_version; - dxdriverfilep->mVersion.set(driver_version); - dxdriverfilep->mDateString = driver_date; - - dxdevicep->mDriverFiles[driver_name] = dxdriverfilep; - - SAFE_RELEASE(file_containerp); - } - SAFE_RELEASE(device_containerp); - } - */ - } - - // dumpDevices(); - ok = true; - -LCleanup: - if (!ok) - { - LL_WARNS("AppInit") << "DX9 probe failed" << LL_ENDL; - gWriteDebug("DX9 probe failed\n"); - } - - SAFE_RELEASE(file_containerp); - SAFE_RELEASE(driver_containerp); - SAFE_RELEASE(device_containerp); - SAFE_RELEASE(devices_containerp); - SAFE_RELEASE(dx_diag_rootp); - SAFE_RELEASE(dx_diag_providerp); - - CoUninitialize(); - - return ok; - } - LLSD LLDXHardware::getDisplayInfo() { LLTimer hw_timer; @@ -995,7 +349,6 @@ LLSD LLDXHardware::getDisplayInfo() if (FAILED(hr)) { LL_WARNS() << "No DXDiag provider found! DirectX 9 not installed!" << LL_ENDL; - gWriteDebug("No DXDiag provider found! DirectX 9 not installed!\n"); goto LCleanup; } if (SUCCEEDED(hr)) // if FAILED(hr) then dx9 is not installed @@ -1111,9 +464,4 @@ LCleanup: return ret; } -void LLDXHardware::setWriteDebugFunc(void (*func)(const char*)) -{ - gWriteDebug = func; -} - #endif diff --git a/indra/llwindow/lldxhardware.h b/indra/llwindow/lldxhardware.h index 2b879e021c..8d8a08a4eb 100644 --- a/indra/llwindow/lldxhardware.h +++ b/indra/llwindow/lldxhardware.h @@ -30,64 +30,16 @@ #include #include "stdtypes.h" -#include "llstring.h" #include "llsd.h" -class LLVersion -{ -public: - LLVersion(); - bool set(const std::string &version_string); - S32 getField(const S32 field_num); -protected: - std::string mVersionString; - S32 mFields[4]; - bool mValid; -}; - -class LLDXDriverFile -{ -public: - std::string dump(); - -public: - std::string mFilepath; - std::string mName; - std::string mVersionString; - LLVersion mVersion; - std::string mDateString; -}; - -class LLDXDevice -{ -public: - ~LLDXDevice(); - std::string dump(); - - LLDXDriverFile *findDriver(const std::string &driver); -public: - std::string mName; - std::string mPCIString; - std::string mVendorID; - std::string mDeviceID; - - typedef std::map driver_file_map_t; - driver_file_map_t mDriverFiles; -}; - class LLDXHardware { public: LLDXHardware(); - void setWriteDebugFunc(void (*func)(const char*)); void cleanup(); - // Returns true on success. - // vram_only true does a "light" probe. - bool getInfo(bool vram_only); - // WMI can return multiple GPU drivers // specify which one to output typedef enum { @@ -98,29 +50,9 @@ public: } EGPUVendor; std::string getDriverVersionWMI(EGPUVendor vendor); - S32 getVRAM() const { return mVRAM; } - LLSD getDisplayInfo(); - - // Will get memory of best GPU in MB, return memory on sucsess, 0 on failure - // Note: WMI is not accurate in some cases - static U32 getMBVideoMemoryViaWMI(); - - // Find a particular device that matches the following specs. - // Empty strings indicate that you don't care. - // You can separate multiple devices with '|' chars to indicate you want - // ANY of them to match and return. - // LLDXDevice *findDevice(const std::string &vendor, const std::string &devices); - - // std::string dumpDevices(); -public: - typedef std::map device_map_t; - // device_map_t mDevices; -protected: - S32 mVRAM; }; -extern void (*gWriteDebug)(const char* msg); extern LLDXHardware gDXHardware; #endif // LL_LLDXHARDWARE_H diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index aaf2a7ea3e..4f5fa53312 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -842,69 +842,11 @@ void write_debug_dx(const std::string& str) bool LLAppViewerWin32::initHardwareTest() { - // - // Do driver verification and initialization based on DirectX - // hardware polling and driver versions - // - if (true == gSavedSettings.getBOOL("ProbeHardwareOnStartup") && false == gSavedSettings.getBOOL("NoHardwareProbe")) - { - // per DEV-11631 - disable hardware probing for everything - // but vram. - bool vram_only = true; - - LLSplashScreen::update(LLTrans::getString("StartupDetectingHardware")); - - LL_DEBUGS("AppInit") << "Attempting to poll DirectX for hardware info" << LL_ENDL; - gDXHardware.setWriteDebugFunc(write_debug_dx); - bool probe_ok = gDXHardware.getInfo(vram_only); - - if (!probe_ok - && gWarningSettings.getBOOL("AboutDirectX9")) - { - LL_WARNS("AppInit") << "DirectX probe failed, alerting user." << LL_ENDL; - - // Warn them that runnin without DirectX 9 will - // not allow us to tell them about driver issues - std::ostringstream msg; - msg << LLTrans::getString ("MBNoDirectX"); - S32 button = OSMessageBox( - msg.str(), - LLTrans::getString("MBWarning"), - OSMB_YESNO); - if (OSBTN_NO== button) - { - LL_INFOS("AppInit") << "User quitting after failed DirectX 9 detection" << LL_ENDL; - LLWeb::loadURLExternal("http://secondlife.com/support/", false); - return false; - } - gWarningSettings.setBOOL("AboutDirectX9", false); - } - LL_DEBUGS("AppInit") << "Done polling DirectX for hardware info" << LL_ENDL; - - // Only probe once after installation - gSavedSettings.setBOOL("ProbeHardwareOnStartup", false); - - // Disable so debugger can work - std::string splash_msg; - LLStringUtil::format_map_t args; - args["[APP_NAME]"] = LLAppViewer::instance()->getSecondLifeTitle(); - splash_msg = LLTrans::getString("StartupLoading", args); - - LLSplashScreen::update(splash_msg); - } - if (!restoreErrorTrap()) { - LL_WARNS("AppInit") << " Someone took over my exception handler (post hardware probe)!" << LL_ENDL; + LL_WARNS("AppInit") << " Someone took over my exception handler!" << LL_ENDL; } - if (gGLManager.mVRAM == 0) - { - gGLManager.mVRAM = gDXHardware.getVRAM(); - } - - LL_INFOS("AppInit") << "Detected VRAM: " << gGLManager.mVRAM << LL_ENDL; - return true; } diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index f0a26f9c56..d909a95b83 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -13,7 +13,6 @@ Second Life Support Portal - Detecting hardware... Loading [APP_NAME]... Clearing cache... Initializing texture cache... -- cgit v1.3 From f6219fecc3a1387f56791eb31c7d83c74c90ce90 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 18 Apr 2025 16:47:08 +0300 Subject: #3696 Crash at LLFontFreetype::addGlyphFromFont --- indra/llrender/llfontfreetype.cpp | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 649dd369cb..5f04664267 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -654,7 +654,14 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_glyph_type, bitmap_num); LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_glyph_type, bitmap_num); - image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight()); + if (image_gl && image_raw) + { + image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight()); + } + else + { + llassert(false); //images were just inserted by nextOpenPos, they shouldn't be missing + } return gi; } @@ -838,7 +845,12 @@ bool LLFontFreetype::setSubImageBGRA(U32 x, U32 y, U32 bitmap_num, U16 width, U1 { LLImageRaw* image_raw = mFontBitmapCachep->getImageRaw(EFontGlyphType::Color, bitmap_num); llassert(!mIsFallback); - llassert(image_raw && (image_raw->getComponents() == 4)); + if (!image_raw) + { + llassert(false); + return false; + } + llassert(image_raw->getComponents() == 4); // NOTE: inspired by LLImageRaw::setSubImage() U32* image_data = (U32*)image_raw->getData(); @@ -866,10 +878,17 @@ bool LLFontFreetype::setSubImageBGRA(U32 x, U32 y, U32 bitmap_num, U16 width, U1 void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride) const { LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(EFontGlyphType::Grayscale, bitmap_num); - LLImageDataLock lock(image_raw); llassert(!mIsFallback); - llassert(image_raw && (image_raw->getComponents() == 2)); + if (!image_raw) + { + llassert(false); + return; + } + + LLImageDataLock lock(image_raw); + + llassert(image_raw->getComponents() == 2); U8 *target = image_raw->getData(); llassert(target); -- cgit v1.3 From d9e55c44152064133796bfb08f1da524387c1300 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 29 Apr 2025 17:09:19 +0300 Subject: #3997 Crash in a gltf asset enabled region --- indra/llrender/llglslshader.cpp | 6 +++--- indra/newview/gltfscenemanager.cpp | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 50e40a3eb6..3735a99109 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -1076,8 +1076,8 @@ void LLGLSLShader::bind() void LLGLSLShader::bind(U8 variant) { - llassert(mGLTFVariants.size() == LLGLSLShader::NUM_GLTF_VARIANTS); - llassert(variant < LLGLSLShader::NUM_GLTF_VARIANTS); + llassert_always(mGLTFVariants.size() == LLGLSLShader::NUM_GLTF_VARIANTS); + llassert_always(variant < LLGLSLShader::NUM_GLTF_VARIANTS); mGLTFVariants[variant].bind(); } @@ -1085,7 +1085,7 @@ void LLGLSLShader::bind(bool rigged) { if (rigged) { - llassert(mRiggedVariant); + llassert_always(mRiggedVariant); mRiggedVariant->bind(); } else diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp index e0cd762776..9faead9533 100644 --- a/indra/newview/gltfscenemanager.cpp +++ b/indra/newview/gltfscenemanager.cpp @@ -643,6 +643,12 @@ void GLTFSceneManager::render(Asset& asset, U8 variant) return; } + if (gGLTFPBRMetallicRoughnessProgram.mGLTFVariants.size() <= variant) + { + llassert(false); // mGLTFVariants should have been initialized + return; + } + for (U32 ds = 0; ds < 2; ++ds) { RenderData& rd = asset.mRenderData[ds]; -- cgit v1.3 From 3da493295e68481c2437465c1e0846541e9e43d8 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 9 Jul 2025 21:18:12 +0300 Subject: #4296 Crash at renderMorphMasks --- indra/llappearance/lltexlayer.cpp | 29 ++++++++++++++++++----------- indra/llrender/llimagegl.cpp | 27 +++++++++++++++++++++++---- indra/newview/llappviewer.cpp | 13 +++++++++---- 3 files changed, 50 insertions(+), 19 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index aa48a2d621..b3800e6981 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -1293,7 +1293,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC { if (!force_render && !hasMorph()) { - LL_DEBUGS() << "skipping renderMorphMasks for " << getUUID() << LL_ENDL; + LL_DEBUGS("Morph") << "skipping renderMorphMasks for " << getUUID() << LL_ENDL; return; } LL_PROFILE_ZONE_SCOPED; @@ -1325,7 +1325,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC success &= param->render( x, y, width, height ); if (!success && !force_render) { - LL_DEBUGS() << "Failed to render param " << param->getID() << " ; skipping morph mask." << LL_ENDL; + LL_DEBUGS("Morph") << "Failed to render param " << param->getID() << " ; skipping morph mask." << LL_ENDL; return; } } @@ -1365,7 +1365,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC } else { - LL_WARNS() << "Skipping rendering of " << getInfo()->mStaticImageFileName + LL_WARNS("Morph") << "Skipping rendering of " << getInfo()->mStaticImageFileName << "; expected 1 or 4 components." << LL_ENDL; } } @@ -1404,8 +1404,8 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC // We can get bad morph masks during login, on minimize, and occasional gl errors. // We should only be doing this when we believe something has changed with respect to the user's appearance. { - LL_DEBUGS("Avatar") << "gl alpha cache of morph mask not found, doing readback: " << getName() << LL_ENDL; - // clear out a slot if we have filled our cache + LL_DEBUGS("Morph") << "gl alpha cache of morph mask not found, doing readback: " << getName() << LL_ENDL; + // clear out a slot if we have filled our cache S32 max_cache_entries = getTexLayerSet()->getAvatarAppearance()->isSelf() ? 4 : 1; while ((S32)mAlphaCache.size() >= max_cache_entries) { @@ -1444,13 +1444,20 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC } glGetTexImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGBA, GL_UNSIGNED_BYTE, temp); - - U8* alpha_cursor = alpha_data; - U8* pixel = temp; - for (int i = 0; i < pixels; i++) + GLenum error = glGetError(); + if (error != GL_NO_ERROR) + { + LL_INFOS("Morph") << "GL Error while reading back morph texture. Error code: " << error << LL_ENDL; + } + else { - *alpha_cursor++ = pixel[3]; - pixel += 4; + U8* alpha_cursor = alpha_data; + U8* pixel = temp; + for (int i = 0; i < pixels; i++) + { + *alpha_cursor++ = pixel[3]; + pixel += 4; + } } gGL.getTexUnit(0)->disable(); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 3f8903ca09..1db36d91f9 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1870,8 +1870,17 @@ bool LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, (GLint*)&glbytes); if(!imageraw->allocateDataSize(width, height, ncomponents, glbytes)) { - LL_WARNS() << "Memory allocation failed for reading back texture. Size is: " << glbytes << LL_ENDL ; - LL_WARNS() << "width: " << width << "height: " << height << "components: " << ncomponents << LL_ENDL ; + constexpr S64 MAX_GL_BYTES = 2048 * 2048; + if (glbytes > 0 && glbytes <= MAX_GL_BYTES) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Memory allocation failed for reading back texture. Data size: " << glbytes << LL_ENDL; + } + else + { + LL_WARNS() << "Memory allocation failed for reading back texture. Data size is: " << glbytes << LL_ENDL; + LL_WARNS() << "width: " << width << "height: " << height << "components: " << ncomponents << LL_ENDL; + } return false ; } @@ -1882,8 +1891,18 @@ bool LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre { if(!imageraw->allocateDataSize(width, height, ncomponents)) { - LL_WARNS() << "Memory allocation failed for reading back texture." << LL_ENDL ; - LL_WARNS() << "width: " << width << "height: " << height << "components: " << ncomponents << LL_ENDL ; + constexpr F32 MAX_IMAGE_SIZE = 2048 * 2048; + F32 size = (F32)width * (F32)height * (F32)ncomponents; + if (size > 0 && size <= MAX_IMAGE_SIZE) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Memory allocation failed for reading back texture. Data size: " << size << LL_ENDL; + } + else + { + LL_WARNS() << "Memory allocation failed for reading back texture." << LL_ENDL; + LL_WARNS() << "width: " << width << "height: " << height << "components: " << ncomponents << LL_ENDL; + } return false ; } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 9872233e98..f4b2fdfdf7 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2245,10 +2245,7 @@ void errorCallback(LLError::ELevel level, const std::string &error_string) // Callback for LLError::LLUserWarningMsg void errorHandler(const std::string& title_string, const std::string& message_string, S32 code) { - if (!message_string.empty()) - { - OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK); - } + // message is going to hang viewer, create marker first switch (code) { case LLError::LLUserWarningMsg::ERROR_OTHER: @@ -2256,6 +2253,10 @@ void errorHandler(const std::string& title_string, const std::string& message_st break; case LLError::LLUserWarningMsg::ERROR_BAD_ALLOC: LLAppViewer::instance()->createErrorMarker(LAST_EXEC_BAD_ALLOC); + // When system run out of memory and errorHandler gets called from a thread, + // main thread might keep going while OSMessageBox freezes the caller. + // Todo: handle it better, but for now disconnect to avoid making things worse + gDisconnected = true; break; case LLError::LLUserWarningMsg::ERROR_MISSING_FILES: LLAppViewer::instance()->createErrorMarker(LAST_EXEC_MISSING_FILES); @@ -2263,6 +2264,10 @@ void errorHandler(const std::string& title_string, const std::string& message_st default: break; } + if (!message_string.empty()) + { + OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK); + } } void LLAppViewer::initLoggingAndGetLastDuration() -- cgit v1.3 From f03cd219a91740de9f406cfae5bbc15194156c78 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Mon, 11 Aug 2025 18:40:16 +0200 Subject: Fix clang compiler issues due to unused variables --- indra/llrender/llrendertarget.cpp | 16 ---------------- indra/newview/gltf/asset.cpp | 4 ++++ indra/newview/lldrawpoolwater.cpp | 2 -- indra/newview/llstartup.cpp | 2 -- indra/newview/llviewertexture.cpp | 2 -- indra/newview/llvoavatar.cpp | 8 -------- indra/newview/llvoicewebrtc.cpp | 4 ---- 7 files changed, 4 insertions(+), 34 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 38bc5ff331..0b0d69812f 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -492,22 +492,6 @@ U32 LLRenderTarget::getNumTextures() const void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options) { gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index), filter_options == LLTexUnit::TFO_TRILINEAR || filter_options == LLTexUnit::TFO_ANISOTROPIC); - - bool isSRGB = false; - llassert(mInternalFormat.size() > index); - switch (mInternalFormat[index]) - { - case GL_SRGB: - case GL_SRGB8: - case GL_SRGB_ALPHA: - case GL_SRGB8_ALPHA8: - isSRGB = true; - break; - - default: - break; - } - gGL.getTexUnit(channel)->setTextureFilteringOption(filter_options); } diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp index e24aea4a28..28f30ae1c9 100644 --- a/indra/newview/gltf/asset.cpp +++ b/indra/newview/gltf/asset.cpp @@ -589,7 +589,9 @@ bool Asset::prep() for (U32 variant = 0; variant < LLGLSLShader::NUM_GLTF_VARIANTS; ++variant) { +#ifdef SHOW_ASSERT U32 attribute_mask = 0; +#endif // for each mesh for (auto& mesh : mMeshes) { @@ -607,7 +609,9 @@ bool Asset::prep() // all primitives of a given variant and material should all have the same attribute mask llassert(attribute_mask == 0 || primitive.mAttributeMask == attribute_mask); +#ifdef SHOW_ASSERT attribute_mask |= primitive.mAttributeMask; +#endif } } } diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 7d58511d41..cdf3244389 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -143,7 +143,6 @@ void LLDrawPoolWater::renderPostDeferred(S32 pass) gGL.setColorMask(true, true); LLColor3 light_diffuse(0, 0, 0); - F32 light_exp = 0.0f; LLEnvironment& environment = LLEnvironment::instance(); LLSettingsWater::ptr_t pwater = environment.getCurrentWater(); @@ -170,7 +169,6 @@ void LLDrawPoolWater::renderPostDeferred(S32 pass) // Apply magic numbers translating light direction into intensities light_dir.normalize(); F32 ground_proj_sq = light_dir.mV[0] * light_dir.mV[0] + light_dir.mV[1] * light_dir.mV[1]; - light_exp = llmax(32.f, 256.f * powf(ground_proj_sq, 16.0f)); if (0.f < light_diffuse.normalize()) // Normalizing a color? Puzzling... { light_diffuse *= (1.5f + (6.f * ground_proj_sq)); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 2409b71f00..ba7437798a 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -342,13 +342,11 @@ void pump_idle_startup_network(void) { // while there are message to process: // process one then call display_startup() - S32 num_messages = 0; { LockMessageChecker lmc(gMessageSystem); while (lmc.checkAllMessages(gFrameCount, gServicePump)) { display_startup(); - ++num_messages; } lmc.processAcks(); } diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 4a9dd1c1b6..1c3674de1d 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -524,7 +524,6 @@ void LLViewerTexture::updateClass() bool is_low = is_sys_low || over_pct > 0.f; static bool was_low = false; - static bool was_sys_low = false; if (is_low && !was_low) { @@ -542,7 +541,6 @@ void LLViewerTexture::updateClass() } was_low = is_low; - was_sys_low = is_sys_low; if (is_low) { diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index dd59979a6c..283a80a1ed 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -4766,14 +4766,6 @@ bool LLVOAvatar::updateCharacter(LLAgent &agent) } bool visible = isVisible(); - bool is_control_avatar = isControlAvatar(); // capture state to simplify tracing - bool is_attachment = false; - - if (is_control_avatar) - { - LLControlAvatar *cav = dynamic_cast(this); - is_attachment = cav && cav->mRootVolp && cav->mRootVolp->isAttachment(); // For attached animated objects - } // For fading out the names above heads, only let the timer // run if we're visible. diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 627d759df4..72baa393cf 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -2264,7 +2264,6 @@ void LLVoiceWebRTCConnection::processIceUpdatesCoro(connectionPtr_t connection) return; } - bool iceCompleted = false; LLSD body; if (!connection->mIceCandidates.empty() || connection->mIceCompleted) { @@ -2303,7 +2302,6 @@ void LLVoiceWebRTCConnection::processIceUpdatesCoro(connectionPtr_t connection) LLSD body_candidate; body_candidate["completed"] = true; body["candidate"] = body_candidate; - iceCompleted = connection->mIceCompleted; connection->mIceCompleted = false; } @@ -2926,7 +2924,6 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b return; } boost::json::object voice_data = voice_data_parsed.as_object(); - bool new_participant = false; boost::json::object mute; boost::json::object user_gain; for (auto &participant_elem : voice_data) @@ -2979,7 +2976,6 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b } } - new_participant |= joined; if (!participant && joined && (primary || !isSpatial())) { participant = LLWebRTCVoiceClient::getInstance()->addParticipantByID(mChannelID, agent_id, mRegionID); -- cgit v1.3 From 99ce597b54a9180cff0f8907e94833257b77e263 Mon Sep 17 00:00:00 2001 From: Rye Date: Thu, 27 Feb 2025 19:28:01 -0500 Subject: Fix texture filtering and address mode not updating for vast majority of textures when dirtied --- indra/llrender/llrender.cpp | 22 +++++++++++++++++++--- indra/llrender/llrender.h | 4 ++++ 2 files changed, 23 insertions(+), 3 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index c26e9b15b8..4f646cdc33 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -207,6 +207,12 @@ void LLTexUnit::bindFast(LLTexture* texture) } glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture); mHasMipMaps = gl_tex->mHasMipMaps; + if (gl_tex->mTexOptionsDirty) + { + gl_tex->mTexOptionsDirty = false; + setTextureAddressModeFast(gl_tex->mAddressMode); + setTextureFilteringOptionFast(gl_tex->mFilterOption); + } } bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind) @@ -461,11 +467,16 @@ void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode) activate(); - glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]); - glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_T, sGLAddressMode[mode]); + setTextureAddressModeFast(mode); +} + +void LLTexUnit::setTextureAddressModeFast(eTextureAddressMode mode) +{ + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]); + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_T, sGLAddressMode[mode]); if (mCurrTexType == TT_CUBE_MAP) { - glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, sGLAddressMode[mode]); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, sGLAddressMode[mode]); } } @@ -475,6 +486,11 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio gGL.flush(); + setTextureFilteringOptionFast(option); +} + +void LLTexUnit::setTextureFilteringOptionFast(LLTexUnit::eTextureFilterOptions option) +{ if (option == TFO_POINT) { glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_NEAREST); diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 9e68c2dcd1..755aee4bd6 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -208,11 +208,15 @@ public: // Warning: this stays set for the bound texture forever, // make sure you want to permanently change the address mode for the bound texture. void setTextureAddressMode(eTextureAddressMode mode); + // MUST already be active and bound + void setTextureAddressModeFast(eTextureAddressMode mode); // Sets the filtering options used to sample the texture // Warning: this stays set for the bound texture forever, // make sure you want to permanently change the filtering for the bound texture. void setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option); + // MUST already be active and bound + void setTextureFilteringOptionFast(LLTexUnit::eTextureFilterOptions option); static U32 getInternalType(eTextureType type); -- cgit v1.3 From 24aef9a98267ee07f3771f010b9e35de392e8355 Mon Sep 17 00:00:00 2001 From: Rye Date: Fri, 22 Aug 2025 13:12:43 -0400 Subject: Fix large performance drop when enabling AA on macOS/lower end GPU hardware --- indra/llrender/llimagegl.cpp | 1 + .../app_settings/shaders/class1/deferred/SMAA.glsl | 16 ++++- indra/newview/llgltfmaterialpreviewmgr.cpp | 10 +-- indra/newview/pipeline.cpp | 78 ++++++++++++++-------- indra/newview/pipeline.h | 3 +- 5 files changed, 72 insertions(+), 36 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 1db36d91f9..52738ec626 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -338,6 +338,7 @@ S32 LLImageGL::dataFormatBits(S32 dataformat) case GL_BGRA: return 32; // Used for QuickTime media textures on the Mac case GL_DEPTH_COMPONENT: return 24; case GL_DEPTH_COMPONENT24: return 24; + case GL_RGBA16: return 64; case GL_R16F: return 16; case GL_RG16F: return 32; case GL_RGB16F: return 48; diff --git a/indra/newview/app_settings/shaders/class1/deferred/SMAA.glsl b/indra/newview/app_settings/shaders/class1/deferred/SMAA.glsl index fdb77cce6e..5837308965 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/SMAA.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/SMAA.glsl @@ -1351,6 +1351,10 @@ float4 SMAABlendingWeightCalculationPS(float2 texcoord, //----------------------------------------------------------------------------- // Neighborhood Blending Pixel Shader (Third Pass) +vec3 srgb_to_linear(vec3 cs); +vec4 srgb_to_linear4(vec4 cs); +vec3 linear_to_srgb(vec3 cl); + float4 SMAANeighborhoodBlendingPS(float2 texcoord, float4 offset, SMAATexture2D(colorTex), @@ -1369,6 +1373,7 @@ float4 SMAANeighborhoodBlendingPS(float2 texcoord, SMAA_BRANCH if (dot(a, float4(1.0, 1.0, 1.0, 1.0)) < 1e-5) { float4 color = SMAASampleLevelZero(colorTex, texcoord); + color.rgb = srgb_to_linear(color.rgb); #if SMAA_REPROJECTION float2 velocity = SMAA_DECODE_VELOCITY(SMAASampleLevelZero(velocityTex, texcoord)); @@ -1377,6 +1382,7 @@ float4 SMAANeighborhoodBlendingPS(float2 texcoord, color.a = sqrt(5.0 * length(velocity)); #endif + color.rgb = linear_to_srgb(color.rgb); return color; } else { bool h = max(a.x, a.z) > max(a.y, a.w); // max(horizontal) > max(vertical) @@ -1393,8 +1399,13 @@ float4 SMAANeighborhoodBlendingPS(float2 texcoord, // We exploit bilinear filtering to mix current pixel with the chosen // neighbor: - float4 color = blendingWeight.x * SMAASampleLevelZero(colorTex, blendingCoord.xy); - color += blendingWeight.y * SMAASampleLevelZero(colorTex, blendingCoord.zw); + float4 color = SMAASampleLevelZero(colorTex, blendingCoord.xy); + color.rgb = srgb_to_linear(color.rgb); + color = blendingWeight.x * color; + + float4 color2 = SMAASampleLevelZero(colorTex, blendingCoord.zw); + color2.rgb = srgb_to_linear(color2.rgb); + color += blendingWeight.y * color2; #if SMAA_REPROJECTION // Antialias velocity for proper reprojection in a later stage: @@ -1405,6 +1416,7 @@ float4 SMAANeighborhoodBlendingPS(float2 texcoord, color.a = sqrt(5.0 * length(velocity)); #endif + color.rgb = linear_to_srgb(color.rgb); return color; } } diff --git a/indra/newview/llgltfmaterialpreviewmgr.cpp b/indra/newview/llgltfmaterialpreviewmgr.cpp index da1f1a466f..5a6e9565ae 100644 --- a/indra/newview/llgltfmaterialpreviewmgr.cpp +++ b/indra/newview/llgltfmaterialpreviewmgr.cpp @@ -523,12 +523,12 @@ bool LLGLTFPreviewTexture::render() gPipeline.copyScreenSpaceReflections(&screen, &gPipeline.mSceneMap); gPipeline.generateLuminance(&screen, &gPipeline.mLuminanceMap); gPipeline.generateExposure(&gPipeline.mLuminanceMap, &gPipeline.mExposureMap, /*use_history = */ false); - gPipeline.gammaCorrect(&screen, &gPipeline.mPostMap); + gPipeline.gammaCorrect(&screen, &gPipeline.mPostPingMap); LLVertexBuffer::unbind(); - gPipeline.generateGlow(&gPipeline.mPostMap); - gPipeline.combineGlow(&gPipeline.mPostMap, &screen); - gPipeline.renderDoF(&screen, &gPipeline.mPostMap); - gPipeline.applyFXAA(&gPipeline.mPostMap, &screen); + gPipeline.generateGlow(&gPipeline.mPostPingMap); + gPipeline.combineGlow(&gPipeline.mPostPingMap, &screen); + gPipeline.renderDoF(&screen, &gPipeline.mPostPingMap); + gPipeline.applyFXAA(&gPipeline.mPostPingMap, &screen); // *HACK: Restore mExposureMap (it will be consumed by generateExposure next frame) gPipeline.mExposureMap.swapFBORefs(gPipeline.mLastExposure); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 4df8936d4d..0120e1487e 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -856,12 +856,12 @@ bool LLPipeline::allocateScreenBufferInternal(U32 resX, U32 resY) GLuint screenFormat = hdr ? GL_RGBA16F : GL_RGBA; - if (!mRT->screen.allocate(resX, resY, GL_RGBA16F)) return false; + if (!mRT->screen.allocate(resX, resY, screenFormat)) return false; mRT->deferredScreen.shareDepthBuffer(mRT->screen); - if (shadow_detail > 0 || ssao || RenderDepthOfField) - { //only need mRT->deferredLight for shadows OR ssao OR dof + if (hdr || shadow_detail > 0 || ssao || RenderDepthOfField) + { //only need mRT->deferredLight for hdr OR shadows OR ssao OR dof if (!mRT->deferredLight.allocate(resX, resY, screenFormat)) return false; } else @@ -907,7 +907,8 @@ bool LLPipeline::allocateScreenBufferInternal(U32 resX, U32 resY) mSceneMap.release(); } - mPostMap.allocate(resX, resY, screenFormat); + mPostPingMap.allocate(resX, resY, GL_RGBA); + mPostPongMap.allocate(resX, resY, GL_RGBA); // The water exclusion mask needs its own depth buffer so we can take care of the problem of multiple water planes. // Should we ever make water not just a plane, it also aids with that as well as the water planes will be rendered into the mask. @@ -1179,7 +1180,8 @@ void LLPipeline::releaseGLBuffers() mWaterExclusionMask.release(); - mPostMap.release(); + mPostPingMap.release(); + mPostPongMap.release(); mFXAAMap.release(); @@ -7585,14 +7587,14 @@ void LLPipeline::generateSMAABuffers(LLRenderTarget* src) { if (!use_sample) { - src->bindTexture(0, channel, LLTexUnit::TFO_POINT); - gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + src->bindTexture(0, channel, LLTexUnit::TFO_BILINEAR); } else { gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mSMAASampleMap); - gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); } + gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); } //if (use_stencil) @@ -7986,7 +7988,7 @@ void LLPipeline::renderFinalize() static LLCachedControl has_hdr(gSavedSettings, "RenderHDREnabled", true); bool hdr = gGLManager.mGLVersion > 4.05f && has_hdr(); - + LLRenderTarget* postHDRBuffer = &mRT->screen; if (hdr) { copyScreenSpaceReflections(&mRT->screen, &mSceneMap); @@ -7995,22 +7997,31 @@ void LLPipeline::renderFinalize() generateExposure(&mLuminanceMap, &mExposureMap); - tonemap(&mRT->screen, &mPostMap); + tonemap(&mRT->screen, &mRT->deferredLight); - applyCAS(&mPostMap, &mRT->screen); + static LLCachedControl cas_sharpness(gSavedSettings, "RenderCASSharpness", 0.4f); + if (cas_sharpness != 0.0f && gCASProgram.isComplete()) + { + applyCAS(&mRT->deferredLight, &mRT->screen); + postHDRBuffer = &mRT->screen; + } + else + { + postHDRBuffer = &mRT->deferredLight; + } } - generateSMAABuffers(&mRT->screen); - - gammaCorrect(&mRT->screen, &mPostMap); + gammaCorrect(postHDRBuffer, &mPostPingMap); LLVertexBuffer::unbind(); - applySMAA(&mPostMap, &mRT->screen); + generateGlow(&mPostPingMap); - generateGlow(&mRT->screen); + LLRenderTarget* sourceBuffer = &mPostPingMap; + LLRenderTarget* targetBuffer = &mPostPongMap; - combineGlow(&mRT->screen, &mPostMap); + combineGlow(sourceBuffer, targetBuffer); + std::swap(sourceBuffer, targetBuffer); gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; @@ -8018,13 +8029,24 @@ void LLPipeline::renderFinalize() gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); - renderDoF(&mPostMap, &mRT->screen); + if((RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) && + RenderDepthOfField && + !gCubeSnapshot) + { + renderDoF(sourceBuffer, targetBuffer); + std::swap(sourceBuffer, targetBuffer); + } - LLRenderTarget* finalBuffer = &mRT->screen; - if (RenderFSAAType == 1) + if (RenderFSAAType == 1) + { + applyFXAA(sourceBuffer, targetBuffer); + std::swap(sourceBuffer, targetBuffer); + } + else if (RenderFSAAType == 2) { - applyFXAA(&mRT->screen, &mPostMap); - finalBuffer = &mPostMap; + generateSMAABuffers(sourceBuffer); + applySMAA(sourceBuffer, targetBuffer); + std::swap(sourceBuffer, targetBuffer); } if (RenderBufferVisualization > -1) @@ -8035,16 +8057,16 @@ void LLPipeline::renderFinalize() case 1: case 2: case 3: - visualizeBuffers(&mRT->deferredScreen, finalBuffer, RenderBufferVisualization); + visualizeBuffers(&mRT->deferredScreen, sourceBuffer, RenderBufferVisualization); break; case 4: - visualizeBuffers(&mLuminanceMap, finalBuffer, 0); + visualizeBuffers(&mLuminanceMap, sourceBuffer, 0); break; case 5: { if (RenderFSAAType > 0) { - visualizeBuffers(&mFXAAMap, finalBuffer, 0); + visualizeBuffers(&mFXAAMap, sourceBuffer, 0); } break; } @@ -8052,7 +8074,7 @@ void LLPipeline::renderFinalize() { if (RenderFSAAType == 2) { - visualizeBuffers(&mSMAABlendBuffer, finalBuffer, 0); + visualizeBuffers(&mSMAABlendBuffer, sourceBuffer, 0); } break; } @@ -8066,10 +8088,10 @@ void LLPipeline::renderFinalize() gDeferredPostNoDoFNoiseProgram.bind(); // Add noise as part of final render to screen pass to avoid damaging other post effects // Whatever is last in the above post processing chain should _always_ be rendered directly here. If not, expect problems. - gDeferredPostNoDoFNoiseProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, finalBuffer); + gDeferredPostNoDoFNoiseProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, sourceBuffer); gDeferredPostNoDoFNoiseProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true); - gDeferredPostNoDoFNoiseProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)finalBuffer->getWidth(), (GLfloat)finalBuffer->getHeight()); + gDeferredPostNoDoFNoiseProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)sourceBuffer->getWidth(), (GLfloat)sourceBuffer->getHeight()); { LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 315e38ed8c..b3796a6feb 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -730,7 +730,8 @@ public: LLRenderTarget mLastExposure; // tonemapped and gamma corrected render ready for post - LLRenderTarget mPostMap; + LLRenderTarget mPostPingMap; + LLRenderTarget mPostPongMap; // FXAA helper target LLRenderTarget mFXAAMap; -- cgit v1.3 From 3ea1d87a42bfc6aba367b1285e7bb6bdf49f8364 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 2 Sep 2025 23:26:16 +0300 Subject: #4587 Shaders sometimes do not match the shader settings Ensure versions get matched reliably --- indra/llrender/llshadermgr.cpp | 36 ++++++++++++++++++++++++++++-------- indra/llrender/llshadermgr.h | 4 ++-- indra/newview/llviewershadermgr.cpp | 11 +++++++++-- 3 files changed, 39 insertions(+), 12 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 4807c12226..0ec532a55b 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -989,16 +989,17 @@ bool LLShaderMgr::validateProgramObject(GLuint obj) return success; } -void LLShaderMgr::initShaderCache(bool enabled, const LLUUID& old_cache_version, const LLUUID& current_cache_version) +void LLShaderMgr::initShaderCache(bool enabled, const LLUUID& old_cache_version, const LLUUID& current_cache_version, bool second_instance) { + LL_PROFILE_ZONE_SCOPED; LL_INFOS() << "Initializing shader cache" << LL_ENDL; mShaderCacheEnabled = gGLManager.mGLVersion >= 4.09 && enabled; - if(!mShaderCacheEnabled || mShaderCacheInitialized) + if(!mShaderCacheEnabled || mShaderCacheVersion.notNull()) return; - mShaderCacheInitialized = true; + mShaderCacheVersion = current_cache_version; mShaderCacheDir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "shader_cache"); LLFile::mkdir(mShaderCacheDir); @@ -1007,16 +1008,19 @@ void LLShaderMgr::initShaderCache(bool enabled, const LLUUID& old_cache_version, std::string meta_out_path = gDirUtilp->add(mShaderCacheDir, "shaderdata.llsd"); if (gDirUtilp->fileExists(meta_out_path)) { + LL_PROFILE_ZONE_NAMED("shader_cache"); LL_INFOS() << "Loading shader cache metadata" << LL_ENDL; llifstream instream(meta_out_path); LLSD in_data; + // todo: this is likely very expensive to parse, should use binary LLSDSerialize::fromNotation(in_data, instream, LLSDSerialize::SIZE_UNLIMITED); instream.close(); - if (old_cache_version == current_cache_version) + if (old_cache_version == current_cache_version + && in_data["version"].asUUID() == current_cache_version) { - for (const auto& data_pair : llsd::inMap(in_data)) + for (const auto& data_pair : llsd::inMap(in_data["shaders"])) { ProgramBinaryData binary_info = ProgramBinaryData(); binary_info.mBinaryFormat = data_pair.second["binary_format"].asInteger(); @@ -1025,11 +1029,15 @@ void LLShaderMgr::initShaderCache(bool enabled, const LLUUID& old_cache_version, mShaderBinaryCache.insert_or_assign(LLUUID(data_pair.first), binary_info); } } - else + else if (!second_instance) { LL_INFOS() << "Shader cache version mismatch detected. Purging." << LL_ENDL; clearShaderCache(); } + else + { + LL_INFOS() << "Shader cache version mismatch detected." << LL_ENDL; + } } } } @@ -1046,10 +1054,22 @@ void LLShaderMgr::clearShaderCache() void LLShaderMgr::persistShaderCacheMetadata() { if(!mShaderCacheEnabled) return; + if (mShaderCacheVersion.isNull()) + { + LL_WARNS() << "Attempted to save shader cache with no version set" << LL_ENDL; + return; + } LL_INFOS() << "Persisting shader cache metadata to disk" << LL_ENDL; - LLSD out = LLSD::emptyMap(); + LLSD out; + // Settings and shader cache get saved at different time, thus making + // RenderShaderCacheVersion unreliable when running multiple viewer + // instances, or for cases where viewer crashes before saving settings. + // Dupplicate version to the cache itself. + out["version"] = mShaderCacheVersion; + out["shaders"] = LLSD::emptyMap(); + LLSD &shaders = out["shaders"]; static const F32 LRU_TIME = (60.f * 60.f) * 24.f * 7.f; // 14 days const F32 current_time = (F32)LLTimer::getTotalSeconds(); @@ -1068,7 +1088,7 @@ void LLShaderMgr::persistShaderCacheMetadata() data["binary_format"] = LLSD::Integer(shader_metadata.mBinaryFormat); data["binary_size"] = LLSD::Integer(shader_metadata.mBinaryLength); data["last_used"] = LLSD::Real(shader_metadata.mLastUsedTime); - out[it->first.asString()] = data; + shaders[it->first.asString()] = data; ++it; } } diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 46788841a5..1b638e6e06 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -363,7 +363,7 @@ public: // Implemented in the application to actually update out of date uniforms for a particular shader virtual void updateShaderUniforms(LLGLSLShader * shader) = 0; // Pure Virtual - void initShaderCache(bool enabled, const LLUUID& old_cache_version, const LLUUID& current_cache_version); + void initShaderCache(bool enabled, const LLUUID& old_cache_version, const LLUUID& current_cache_version, bool second_instance); void clearShaderCache(); void persistShaderCacheMetadata(); @@ -387,7 +387,7 @@ public: F32 mLastUsedTime = 0.0; }; std::map mShaderBinaryCache; - bool mShaderCacheInitialized = false; + LLUUID mShaderCacheVersion; bool mShaderCacheEnabled = false; std::string mShaderCacheDir; diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index a0a9906724..a9c58d5a06 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -545,7 +545,11 @@ void LLViewerShaderMgr::setShaders() gSavedSettings.setString("RenderShaderCacheVersion", current_cache_version.asString()); } - initShaderCache(shader_cache_enabled, old_cache_version, current_cache_version); + initShaderCache( + shader_cache_enabled, + old_cache_version, + current_cache_version, + LLAppViewer::instance()->isSecondInstance()); } static LLCachedControl max_texture_index(gSavedSettings, "RenderMaxTextureIndex", 16); @@ -703,7 +707,10 @@ void LLViewerShaderMgr::setShaders() loaded = loaded && loadShadersDeferred(); llassert(loaded); - persistShaderCacheMetadata(); + if (!LLAppViewer::instance()->isSecondInstance()) + { + persistShaderCacheMetadata(); + } if (gViewerWindow) { -- cgit v1.3 From 46f325b7db41ac855d35e3ab50ad915dd075de1e Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 2 Sep 2025 23:29:06 +0300 Subject: #4587 Make shader cache reading faster --- indra/llrender/llshadermgr.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 0ec532a55b..a4d5282b0c 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -992,7 +992,7 @@ bool LLShaderMgr::validateProgramObject(GLuint obj) void LLShaderMgr::initShaderCache(bool enabled, const LLUUID& old_cache_version, const LLUUID& current_cache_version, bool second_instance) { LL_PROFILE_ZONE_SCOPED; - LL_INFOS() << "Initializing shader cache" << LL_ENDL; + LL_INFOS("ShaderMgr") << "Initializing shader cache" << LL_ENDL; mShaderCacheEnabled = gGLManager.mGLVersion >= 4.09 && enabled; @@ -1009,12 +1009,12 @@ void LLShaderMgr::initShaderCache(bool enabled, const LLUUID& old_cache_version, if (gDirUtilp->fileExists(meta_out_path)) { LL_PROFILE_ZONE_NAMED("shader_cache"); - LL_INFOS() << "Loading shader cache metadata" << LL_ENDL; + LL_INFOS("ShaderMgr") << "Loading shader cache metadata" << LL_ENDL; - llifstream instream(meta_out_path); + llifstream instream(meta_out_path, std::ifstream::in | std::ifstream::binary); LLSD in_data; // todo: this is likely very expensive to parse, should use binary - LLSDSerialize::fromNotation(in_data, instream, LLSDSerialize::SIZE_UNLIMITED); + LLSDSerialize::fromBinary(in_data, instream, LLSDSerialize::SIZE_UNLIMITED); instream.close(); if (old_cache_version == current_cache_version @@ -1031,12 +1031,12 @@ void LLShaderMgr::initShaderCache(bool enabled, const LLUUID& old_cache_version, } else if (!second_instance) { - LL_INFOS() << "Shader cache version mismatch detected. Purging." << LL_ENDL; + LL_INFOS("ShaderMgr") << "Shader cache version mismatch detected. Purging." << LL_ENDL; clearShaderCache(); } else { - LL_INFOS() << "Shader cache version mismatch detected." << LL_ENDL; + LL_INFOS("ShaderMgr") << "Shader cache version mismatch detected." << LL_ENDL; } } } @@ -1045,7 +1045,7 @@ void LLShaderMgr::initShaderCache(bool enabled, const LLUUID& old_cache_version, void LLShaderMgr::clearShaderCache() { std::string shader_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "shader_cache"); - LL_INFOS() << "Removing shader cache at " << shader_cache << LL_ENDL; + LL_INFOS("ShaderMgr") << "Removing shader cache at " << shader_cache << LL_ENDL; const std::string mask = "*"; gDirUtilp->deleteFilesInDir(shader_cache, mask); mShaderBinaryCache.clear(); @@ -1056,11 +1056,11 @@ void LLShaderMgr::persistShaderCacheMetadata() if(!mShaderCacheEnabled) return; if (mShaderCacheVersion.isNull()) { - LL_WARNS() << "Attempted to save shader cache with no version set" << LL_ENDL; + LL_WARNS("ShaderMgr") << "Attempted to save shader cache with no version set" << LL_ENDL; return; } - LL_INFOS() << "Persisting shader cache metadata to disk" << LL_ENDL; + LL_INFOS("ShaderMgr") << "Persisting shader cache metadata to disk" << LL_ENDL; LLSD out; // Settings and shader cache get saved at different time, thus making @@ -1094,8 +1094,13 @@ void LLShaderMgr::persistShaderCacheMetadata() } std::string meta_out_path = gDirUtilp->add(mShaderCacheDir, "shaderdata.llsd"); - llofstream outstream(meta_out_path); - LLSDSerialize::toNotation(out, outstream); + llofstream outstream(meta_out_path, std::ios_base::out | std::ios_base::binary); + if (!outstream.is_open()) + { + LL_WARNS("ShaderMgr") << "Failed to open file. Unable to save shader cache to: " << mShaderCacheDir << LL_ENDL; + return; + } + LLSDSerialize::toBinary(out, outstream); outstream.close(); } -- cgit v1.3 From 97ff76c420cfaf32e7ad4602506917666129253c Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 24 Sep 2025 18:10:29 +0300 Subject: #4733 When moving the cache, the old cef_cache should be removed --- indra/llrender/llshadermgr.cpp | 1 + indra/newview/llappviewer.cpp | 1 + 2 files changed, 2 insertions(+) (limited to 'indra/llrender') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 9cdd02f403..e9bbdeead5 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1048,6 +1048,7 @@ void LLShaderMgr::clearShaderCache() LL_INFOS("ShaderMgr") << "Removing shader cache at " << shader_cache << LL_ENDL; const std::string mask = "*"; gDirUtilp->deleteFilesInDir(shader_cache, mask); + LLFile::rmdir(shader_cache); mShaderBinaryCache.clear(); } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 3d2946b8aa..4a4a2bdbb3 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -4481,6 +4481,7 @@ void LLAppViewer::purgeCache() LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE); LLVOCache::getInstance()->removeCache(LL_PATH_CACHE); LLViewerShaderMgr::instance()->clearShaderCache(); + purgeCefStaleCaches(); gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), "*"); } -- cgit v1.3 From 79909b8a335b9fdeaefe384528284538e8dae6a4 Mon Sep 17 00:00:00 2001 From: Rye Date: Mon, 29 Sep 2025 12:23:29 -0400 Subject: Fix rendering differences observed in 2025.07 (#4747) * Fix calling setTextureAddressModeFast and setTextureFilteringOptionFast with invalid tex type during fast binds * Restore mRT->screen to GL_RGBA16F to fix lighting banding --- indra/llrender/llrender.cpp | 38 +++++++++++++++++++------------------- indra/llrender/llrender.h | 4 ++-- indra/newview/pipeline.cpp | 2 +- 3 files changed, 22 insertions(+), 22 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 4f646cdc33..57be8570af 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -210,8 +210,8 @@ void LLTexUnit::bindFast(LLTexture* texture) if (gl_tex->mTexOptionsDirty) { gl_tex->mTexOptionsDirty = false; - setTextureAddressModeFast(gl_tex->mAddressMode); - setTextureFilteringOptionFast(gl_tex->mFilterOption); + setTextureAddressModeFast(gl_tex->mAddressMode, gl_tex->getTarget()); + setTextureFilteringOptionFast(gl_tex->mFilterOption, gl_tex->getTarget()); } } @@ -467,16 +467,16 @@ void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode) activate(); - setTextureAddressModeFast(mode); + setTextureAddressModeFast(mode, mCurrTexType); } -void LLTexUnit::setTextureAddressModeFast(eTextureAddressMode mode) +void LLTexUnit::setTextureAddressModeFast(eTextureAddressMode mode, eTextureType tex_type) { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]); - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_T, sGLAddressMode[mode]); - if (mCurrTexType == TT_CUBE_MAP) + glTexParameteri(sGLTextureType[tex_type], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]); + glTexParameteri(sGLTextureType[tex_type], GL_TEXTURE_WRAP_T, sGLAddressMode[mode]); + if (tex_type == TT_CUBE_MAP || tex_type == TT_CUBE_MAP_ARRAY || tex_type == TT_TEXTURE_3D) { - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, sGLAddressMode[mode]); + glTexParameteri(sGLTextureType[tex_type], GL_TEXTURE_WRAP_R, sGLAddressMode[mode]); } } @@ -486,44 +486,44 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio gGL.flush(); - setTextureFilteringOptionFast(option); + setTextureFilteringOptionFast(option, mCurrTexType); } -void LLTexUnit::setTextureFilteringOptionFast(LLTexUnit::eTextureFilterOptions option) +void LLTexUnit::setTextureFilteringOptionFast(LLTexUnit::eTextureFilterOptions option, eTextureType tex_type) { if (option == TFO_POINT) { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(sGLTextureType[tex_type], GL_TEXTURE_MAG_FILTER, GL_NEAREST); } else { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(sGLTextureType[tex_type], GL_TEXTURE_MAG_FILTER, GL_LINEAR); } if (option >= TFO_TRILINEAR && mHasMipMaps) { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(sGLTextureType[tex_type], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } else if (option >= TFO_BILINEAR) { if (mHasMipMaps) { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + glTexParameteri(sGLTextureType[tex_type], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); } else { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(sGLTextureType[tex_type], GL_TEXTURE_MIN_FILTER, GL_LINEAR); } } else { if (mHasMipMaps) { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + glTexParameteri(sGLTextureType[tex_type], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); } else { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(sGLTextureType[tex_type], GL_TEXTURE_MIN_FILTER, GL_NEAREST); } } @@ -531,11 +531,11 @@ void LLTexUnit::setTextureFilteringOptionFast(LLTexUnit::eTextureFilterOptions o { if (LLImageGL::sGlobalUseAnisotropic && option == TFO_ANISOTROPIC) { - glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY, gGLManager.mMaxAnisotropy); + glTexParameterf(sGLTextureType[tex_type], GL_TEXTURE_MAX_ANISOTROPY, gGLManager.mMaxAnisotropy); } else { - glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY, 1.f); + glTexParameterf(sGLTextureType[tex_type], GL_TEXTURE_MAX_ANISOTROPY, 1.f); } } } diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 755aee4bd6..0801c12fb4 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -209,14 +209,14 @@ public: // make sure you want to permanently change the address mode for the bound texture. void setTextureAddressMode(eTextureAddressMode mode); // MUST already be active and bound - void setTextureAddressModeFast(eTextureAddressMode mode); + void setTextureAddressModeFast(eTextureAddressMode mode, eTextureType tex_type); // Sets the filtering options used to sample the texture // Warning: this stays set for the bound texture forever, // make sure you want to permanently change the filtering for the bound texture. void setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option); // MUST already be active and bound - void setTextureFilteringOptionFast(LLTexUnit::eTextureFilterOptions option); + void setTextureFilteringOptionFast(LLTexUnit::eTextureFilterOptions option, eTextureType tex_type); static U32 getInternalType(eTextureType type); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 2fe67a5457..856dee3dd4 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -858,7 +858,7 @@ bool LLPipeline::allocateScreenBufferInternal(U32 resX, U32 resY) GLuint screenFormat = hdr ? GL_RGBA16F : GL_RGBA; - if (!mRT->screen.allocate(resX, resY, screenFormat)) return false; + if (!mRT->screen.allocate(resX, resY, GL_RGBA16F)) return false; mRT->deferredScreen.shareDepthBuffer(mRT->screen); -- cgit v1.3 From ee6a9e7ed10f775bce312a0b8911ea8721342250 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Tue, 30 Sep 2025 22:44:40 +0300 Subject: #4758 Extra logging to track discard 6 Plus clamped some values and preventing decode from starting --- indra/llrender/llimagegl.cpp | 3 ++- indra/newview/lltexturefetch.cpp | 21 +++++++++++++++++---- indra/newview/llviewertexture.cpp | 2 +- 3 files changed, 20 insertions(+), 6 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 52738ec626..94115a06fd 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1544,7 +1544,7 @@ bool LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S if (discard_level < 0) { llassert(mCurrentDiscardLevel >= 0); - discard_level = mCurrentDiscardLevel; + discard_level = llmin(mCurrentDiscardLevel, MAX_DISCARD_LEVEL); } // Actual image width/height = raw image width/height * 2^discard_level @@ -1644,6 +1644,7 @@ bool LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, bool data_ discard_level = mCurrentDiscardLevel; } discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); + discard_level = llmin(discard_level, MAX_DISCARD_LEVEL); if (main_thread // <--- always force creation of new_texname when not on main thread ... && !defer_copy // <--- ... or defer copy is set diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 8b991f3f34..f7cb0ee7ed 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1703,10 +1703,10 @@ bool LLTextureFetchWorker::doWork(S32 param) mHttpReplyOffset = 0; mLoadedDiscard = mRequestedDiscard; - if (mLoadedDiscard < 0) + if (mLoadedDiscard < 0 || (mLoadedDiscard > MAX_DISCARD_LEVEL && mFormattedImage->getCodec() == IMG_CODEC_J2C)) { LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard - << ", should be >=0" << LL_ENDL; + << ", should be >=0 and <=" << MAX_DISCARD_LEVEL << LL_ENDL; } setState(DECODE_IMAGE); if (mWriteToCacheState != NOT_WRITE) @@ -1768,14 +1768,27 @@ bool LLTextureFetchWorker::doWork(S32 param) LL_DEBUGS(LOG_TXT) << mID << " DECODE_IMAGE abort: mLoadedDiscard < 0" << LL_ENDL; return true; } + + llassert_always(mFormattedImage.notNull()); + S32 discard = mHaveAllData && mFormattedImage->getCodec() != IMG_CODEC_J2C ? 0 : mLoadedDiscard; + if (discard > MAX_DISCARD_LEVEL) // only warn for j2c + { + // We encode j2c with fixed amount of discard levels, + // Trying to decode beyound that will fail. + LL_WARNS(LOG_TXT) << "Decode entered with invalid discard. ID = " << mID << LL_ENDL; + + //abort, don't decode + setState(DONE); + LL_DEBUGS(LOG_TXT) << mID << " DECODE_IMAGE abort: mLoadedDiscard > MAX_DISCARD_LEVEL" << LL_ENDL; + return true; + } + mDecodeTimer.reset(); mRawImage = NULL; mAuxImage = NULL; - llassert_always(mFormattedImage.notNull()); // if we have the entire image data (and the image is not J2C), decode the full res image // DO NOT decode a higher res j2c than was requested. This is a waste of time and memory. - S32 discard = mHaveAllData && mFormattedImage->getCodec() != IMG_CODEC_J2C ? 0 : mLoadedDiscard; mDecoded = false; setState(DECODE_IMAGE_UPDATE); LL_DEBUGS(LOG_TXT) << mID << ": Decoding. Bytes: " << mFormattedImage->getDataSize() << " Discard: " << discard diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 3142c9950b..6135e18840 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -2153,7 +2153,7 @@ bool LLViewerFetchedTexture::updateFetch() } const U32 override_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); - if (override_tex_discard_level != 0) + if (override_tex_discard_level != 0 && override_tex_discard_level <= MAX_DISCARD_LEVEL) { desired_discard = override_tex_discard_level; } -- cgit v1.3 From 45528d33280a2ea8ce03211e8e60d9ef991d07ea Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Wed, 1 Oct 2025 20:33:53 +0300 Subject: #4773 Crash on sub_image_lines Just caught it and discard_level is somehow 7, which seems like it resulted in src going out of bounds, which crashed glTexSubImage2D --- indra/llrender/llimagegl.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 94115a06fd..97ea6f67bd 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1097,6 +1097,8 @@ void sub_image_lines(U32 target, S32 miplevel, S32 x_offset, S32 y_offset, S32 w // full width texture, do 32 lines at a time for (U32 y_pos = y_offset; y_pos < y_offset_end; y_pos += batch_size) { + // If this keeps crashing, pass down data_size, looks like it is using + // imageraw->getData(); for data, but goes way over allocated size limit glTexSubImage2D(target, miplevel, x_offset, y_pos, width, batch_size, pixformat, pixtype, src); src += line_width * batch_size; } @@ -1106,6 +1108,8 @@ void sub_image_lines(U32 target, S32 miplevel, S32 x_offset, S32 y_offset, S32 w // partial width or strange height for (U32 y_pos = y_offset; y_pos < y_offset_end; y_pos += 1) { + // If this keeps crashing, pass down data_size, looks like it is using + // imageraw->getData(); for data, but goes way over allocated size limit glTexSubImage2D(target, miplevel, x_offset, y_pos, width, 1, pixformat, pixtype, src); src += line_width; } @@ -1544,8 +1548,9 @@ bool LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S if (discard_level < 0) { llassert(mCurrentDiscardLevel >= 0); - discard_level = llmin(mCurrentDiscardLevel, MAX_DISCARD_LEVEL); + discard_level = mCurrentDiscardLevel; } + discard_level = llmin(discard_level, MAX_DISCARD_LEVEL); // Actual image width/height = raw image width/height * 2^discard_level S32 raw_w = imageraw->getWidth() ; -- cgit v1.3 From 5e28a5de82ce94b4d10142f065f3fd08990ea623 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Sat, 8 Nov 2025 01:33:29 +0200 Subject: #4946 Crash at setShaders Fix wrong delimeter and log if file isn't present --- indra/llrender/llshadermgr.cpp | 15 +++++++++++++-- indra/newview/llviewershadermgr.cpp | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index e9bbdeead5..2c35a6acae 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -511,7 +511,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev { //search from the current gpu class down to class 1 to find the most relevant shader std::stringstream fname; fname << getShaderDirPrefix(); - fname << gpu_class << "/" << filename; + fname << gpu_class << gDirUtilp->getDirDelimiter() << filename; open_file_name = fname.str(); @@ -540,7 +540,14 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev if (file == NULL) { - LL_WARNS("ShaderLoading") << "GLSL Shader file not found: " << open_file_name << LL_ENDL; + if (gDirUtilp->fileExists(open_file_name)) + { + LL_WARNS("ShaderLoading") << "GLSL Shader file failed to open: " << open_file_name << LL_ENDL; + } + else + { + LL_WARNS("ShaderLoading") << "GLSL Shader file not found: " << open_file_name << LL_ENDL; + } return 0; } @@ -857,6 +864,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev //load source if (ret) { + LL_DEBUGS("ShaderLoading") << "glCreateShader done" << LL_ENDL; glShaderSource(ret, shader_code_count, (const GLchar**)shader_code_text, NULL); error = glGetError(); @@ -871,6 +879,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev //compile source if (ret) { + LL_DEBUGS("ShaderLoading") << "glShaderSource done" << U32(ret) << LL_ENDL; glCompileShader(ret); error = glGetError(); @@ -885,6 +894,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev if (error == GL_NO_ERROR) { //check for errors + LL_DEBUGS("ShaderLoading") << "glCompileShader done" << U32(ret) << LL_ENDL; GLint success = GL_TRUE; glGetShaderiv(ret, GL_COMPILE_STATUS, &success); @@ -901,6 +911,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev } else { + LL_DEBUGS("ShaderLoading") << "loadShaderFile() completed, ret: " << U32(ret) << LL_ENDL; ret = 0; } stop_glerror(); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 0c912e8dbc..92141ee67e 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -3562,7 +3562,7 @@ bool LLViewerShaderMgr::loadShadersInterface() std::string LLViewerShaderMgr::getShaderDirPrefix(void) { - return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders/class"); + return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders", "class"); } void LLViewerShaderMgr::updateShaderUniforms(LLGLSLShader * shader) -- cgit v1.3