From 7316441f22e516db17f27a6102e012713c2b0ce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20N=C3=A6sbye=20Christensen?= Date: Fri, 9 Feb 2024 04:25:50 +0100 Subject: llrender: BOOL (int) to real bool --- indra/llrender/llglslshader.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'indra/llrender/llglslshader.cpp') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index ccfb8f69be..65c44ed04c 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -81,7 +81,7 @@ const std::string gShaderConstsVal[LLGLSLShader::NUM_SHADER_CONSTS] = }; -BOOL shouldChange(const LLVector4& v1, const LLVector4& v2) +bool shouldChange(const LLVector4& v1, const LLVector4& v2) { return v1 != v2; } @@ -381,7 +381,7 @@ void LLGLSLShader::unloadInternal() stop_glerror(); } -BOOL LLGLSLShader::createShader(std::vector* attributes, +bool LLGLSLShader::createShader(std::vector* attributes, std::vector* uniforms, U32 varying_count, const char** varyings) @@ -415,10 +415,10 @@ BOOL LLGLSLShader::createShader(std::vector* attributes, // Shouldn't happen if shader related extensions, like ARB_vertex_shader, exist. LL_SHADER_LOADING_WARNS() << "Failed to create handle for shader: " << mName << LL_ENDL; unloadInternal(); - return FALSE; + return false; } - BOOL success = TRUE; + bool success = true; mUsingBinaryProgram = LLShaderMgr::instance()->loadCachedProgramBinary(this); @@ -440,7 +440,7 @@ BOOL LLGLSLShader::createShader(std::vector* attributes, } else { - success = FALSE; + success = false; } } } @@ -449,7 +449,7 @@ BOOL LLGLSLShader::createShader(std::vector* attributes, if (!LLShaderMgr::instance()->attachShaderFeatures(this)) { unloadInternal(); - return FALSE; + return false; } // Map attributes and uniforms if (success) @@ -529,7 +529,7 @@ void dumpAttachObject(const char* func_name, GLuint program_object, const std::s } #endif // DEBUG_SHADER_INCLUDES -BOOL LLGLSLShader::attachVertexObject(std::string object_path) +bool LLGLSLShader::attachVertexObject(std::string object_path) { if (LLShaderMgr::instance()->mVertexShaderObjects.count(object_path) > 0) { @@ -539,19 +539,19 @@ BOOL LLGLSLShader::attachVertexObject(std::string object_path) dumpAttachObject("attachVertexObject", mProgramObject, object_path); #endif // DEBUG_SHADER_INCLUDES stop_glerror(); - return TRUE; + return true; } else { LL_SHADER_LOADING_WARNS() << "Attempting to attach shader object: '" << object_path << "' that hasn't been compiled." << LL_ENDL; - return FALSE; + return false; } } -BOOL LLGLSLShader::attachFragmentObject(std::string object_path) +bool LLGLSLShader::attachFragmentObject(std::string object_path) { if(mUsingBinaryProgram) - return TRUE; + return true; if (LLShaderMgr::instance()->mFragmentShaderObjects.count(object_path) > 0) { @@ -561,12 +561,12 @@ BOOL LLGLSLShader::attachFragmentObject(std::string object_path) dumpAttachObject("attachFragmentObject", mProgramObject, object_path); #endif // DEBUG_SHADER_INCLUDES stop_glerror(); - return TRUE; + return true; } else { LL_SHADER_LOADING_WARNS() << "Attempting to attach shader object: '" << object_path << "' that hasn't been compiled." << LL_ENDL; - return FALSE; + return false; } } -- cgit v1.2.3 From b2c271367296744fbbe2262e55d0ea4f8f5ccdc9 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Tue, 20 Feb 2024 00:50:39 +0100 Subject: Convert BOOL to bool in llrender --- indra/llrender/llglslshader.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'indra/llrender/llglslshader.cpp') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 65c44ed04c..405203b3de 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -309,7 +309,7 @@ LLGLSLShader::LLGLSLShader() mShaderLevel(0), mShaderGroup(SG_DEFAULT), mFeatures(), - mUniformsDirty(FALSE), + mUniformsDirty(false), mTimerQuery(0), mSamplesQuery(0), mPrimitivesQuery(0) @@ -602,11 +602,11 @@ void LLGLSLShader::attachObjects(GLuint* objects, S32 count) } } -BOOL LLGLSLShader::mapAttributes(const std::vector* attributes) +bool LLGLSLShader::mapAttributes(const std::vector* attributes) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - BOOL res = TRUE; + bool res = true; if (!mUsingBinaryProgram) { //before linking, make sure reserved attributes always have consistent locations @@ -663,10 +663,10 @@ BOOL LLGLSLShader::mapAttributes(const std::vector* attrib } } - return TRUE; + return true; } - return FALSE; + return false; } void LLGLSLShader::mapUniform(GLint index, const vector* uniforms) @@ -830,11 +830,11 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type, GLint return -1; } -BOOL LLGLSLShader::mapUniforms(const vector* uniforms) +bool LLGLSLShader::mapUniforms(const vector* uniforms) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - BOOL res = TRUE; + bool res = true; mTotalUniformSize = 0; mActiveTextureChannels = 0; @@ -1001,11 +1001,11 @@ BOOL LLGLSLShader::mapUniforms(const vector* uniforms) } -BOOL LLGLSLShader::link(BOOL suppress_errors) +bool LLGLSLShader::link(bool suppress_errors) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - BOOL success = LLShaderMgr::instance()->linkProgramObject(mProgramObject, suppress_errors); + bool success = LLShaderMgr::instance()->linkProgramObject(mProgramObject, suppress_errors); if (!success && !suppress_errors) { @@ -1045,7 +1045,7 @@ void LLGLSLShader::bind() if (mUniformsDirty) { LLShaderMgr::instance()->updateShaderUniforms(this); - mUniformsDirty = FALSE; + mUniformsDirty = false; } } -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/llrender/llglslshader.cpp | 3904 +++++++++++++++++++-------------------- 1 file changed, 1952 insertions(+), 1952 deletions(-) (limited to 'indra/llrender/llglslshader.cpp') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 5c19931956..1651835b59 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -1,1952 +1,1952 @@ -/** - * @file llglslshader.cpp - * @brief GLSL helper functions and state. - * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llglslshader.h" - -#include "llshadermgr.h" -#include "llfile.h" -#include "llrender.h" -#include "llvertexbuffer.h" -#include "llrendertarget.h" - -#include "hbxxh.h" -#include "llsdserialize.h" - -#if LL_DARWIN -#include "OpenGL/OpenGL.h" -#endif - - // Print-print list of shader included source files that are linked together via glAttachShader() - // i.e. On macOS / OSX the AMD GLSL linker will display an error if a varying is left in an undefined state. -#define DEBUG_SHADER_INCLUDES 0 - -// Lots of STL stuff in here, using namespace std to keep things more readable -using std::vector; -using std::pair; -using std::make_pair; -using std::string; - -GLuint LLGLSLShader::sCurBoundShader = 0; -LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL; -S32 LLGLSLShader::sIndexedTextureChannels = 0; -bool LLGLSLShader::sProfileEnabled = false; -std::set LLGLSLShader::sInstances; -LLGLSLShader::defines_map_t LLGLSLShader::sGlobalDefines; -U64 LLGLSLShader::sTotalTimeElapsed = 0; -U32 LLGLSLShader::sTotalTrianglesDrawn = 0; -U64 LLGLSLShader::sTotalSamplesDrawn = 0; -U32 LLGLSLShader::sTotalBinds = 0; - -//UI shader -- declared here so llui_libtest will link properly -LLGLSLShader gUIProgram; -LLGLSLShader gSolidColorProgram; - -// NOTE: Keep gShaderConsts* and LLGLSLShader::ShaderConsts_e in sync! -const std::string gShaderConstsKey[LLGLSLShader::NUM_SHADER_CONSTS] = -{ - "LL_SHADER_CONST_CLOUD_MOON_DEPTH" - , "LL_SHADER_CONST_STAR_DEPTH" -}; - -// NOTE: Keep gShaderConsts* and LLGLSLShader::ShaderConsts_e in sync! -const std::string gShaderConstsVal[LLGLSLShader::NUM_SHADER_CONSTS] = -{ - "0.99998" // SHADER_CONST_CLOUD_MOON_DEPTH // SL-14113 - , "0.99999" // SHADER_CONST_STAR_DEPTH // SL-14113 -}; - - -bool shouldChange(const LLVector4& v1, const LLVector4& v2) -{ - return v1 != v2; -} - -//=============================== -// LLGLSL Shader implementation -//=============================== - -//static -void LLGLSLShader::initProfile() -{ - sProfileEnabled = true; - sTotalTimeElapsed = 0; - sTotalTrianglesDrawn = 0; - sTotalSamplesDrawn = 0; - sTotalBinds = 0; - - for (std::set::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) - { - (*iter)->clearStats(); - } -} - - -struct LLGLSLShaderCompareTimeElapsed -{ - bool operator()(const LLGLSLShader* const& lhs, const LLGLSLShader* const& rhs) - { - return lhs->mTimeElapsed < rhs->mTimeElapsed; - } -}; - -//static -void LLGLSLShader::finishProfile(bool emit_report) -{ - sProfileEnabled = false; - - if (emit_report) - { - std::vector sorted; - - for (std::set::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) - { - sorted.push_back(*iter); - } - - std::sort(sorted.begin(), sorted.end(), LLGLSLShaderCompareTimeElapsed()); - - bool unbound = false; - for (std::vector::iterator iter = sorted.begin(); iter != sorted.end(); ++iter) - { - (*iter)->dumpStats(); - if ((*iter)->mBinds == 0) - { - unbound = true; - } - } - - LL_INFOS() << "-----------------------------------" << LL_ENDL; - LL_INFOS() << "Total rendering time: " << llformat("%.4f ms", sTotalTimeElapsed / 1000000.f) << LL_ENDL; - LL_INFOS() << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn / 1000000.f) << LL_ENDL; - LL_INFOS() << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn / 1000000.f) << LL_ENDL; - LL_INFOS() << "-----------------------------------" << LL_ENDL; - - if (unbound) - { - LL_INFOS() << "The following shaders were unused: " << LL_ENDL; - for (std::vector::iterator iter = sorted.begin(); iter != sorted.end(); ++iter) - { - if ((*iter)->mBinds == 0) - { - LL_INFOS() << (*iter)->mName << LL_ENDL; - } - } - } - } -} - -void LLGLSLShader::clearStats() -{ - mTrianglesDrawn = 0; - mTimeElapsed = 0; - mSamplesDrawn = 0; - mBinds = 0; -} - -void LLGLSLShader::dumpStats() -{ - if (mBinds > 0) - { - LL_INFOS() << "=============================================" << LL_ENDL; - LL_INFOS() << mName << LL_ENDL; - for (U32 i = 0; i < mShaderFiles.size(); ++i) - { - LL_INFOS() << mShaderFiles[i].first << LL_ENDL; - } - LL_INFOS() << "=============================================" << LL_ENDL; - - F32 ms = mTimeElapsed / 1000000.f; - F32 seconds = ms / 1000.f; - - F32 pct_tris = (F32)mTrianglesDrawn / (F32)sTotalTrianglesDrawn * 100.f; - F32 tris_sec = (F32)(mTrianglesDrawn / 1000000.0); - tris_sec /= seconds; - - F32 pct_samples = (F32)((F64)mSamplesDrawn / (F64)sTotalSamplesDrawn) * 100.f; - F32 samples_sec = (F32)mSamplesDrawn / 1000000000.0; - samples_sec /= seconds; - - F32 pct_binds = (F32)mBinds / (F32)sTotalBinds * 100.f; - - LL_INFOS() << "Triangles Drawn: " << mTrianglesDrawn << " " << llformat("(%.2f pct of total, %.3f million/sec)", pct_tris, tris_sec) << LL_ENDL; - LL_INFOS() << "Binds: " << mBinds << " " << llformat("(%.2f pct of total)", pct_binds) << LL_ENDL; - LL_INFOS() << "SamplesDrawn: " << mSamplesDrawn << " " << llformat("(%.2f pct of total, %.3f billion/sec)", pct_samples, samples_sec) << LL_ENDL; - LL_INFOS() << "Time Elapsed: " << mTimeElapsed << " " << llformat("(%.2f pct of total, %.5f ms)\n", (F32)((F64)mTimeElapsed / (F64)sTotalTimeElapsed) * 100.f, ms) << LL_ENDL; - } -} - -//static -void LLGLSLShader::startProfile() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - if (sProfileEnabled && sCurBoundShaderPtr) - { - sCurBoundShaderPtr->placeProfileQuery(); - } - -} - -//static -void LLGLSLShader::stopProfile() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - if (sProfileEnabled && sCurBoundShaderPtr) - { - sCurBoundShaderPtr->unbind(); - } -} - -void LLGLSLShader::placeProfileQuery(bool for_runtime) -{ - if (sProfileEnabled || for_runtime) - { - if (mTimerQuery == 0) - { - glGenQueries(1, &mSamplesQuery); - glGenQueries(1, &mTimerQuery); - glGenQueries(1, &mPrimitivesQuery); - } - - glBeginQuery(GL_TIME_ELAPSED, mTimerQuery); - - if (!for_runtime) - { - glBeginQuery(GL_SAMPLES_PASSED, mSamplesQuery); - glBeginQuery(GL_PRIMITIVES_GENERATED, mPrimitivesQuery); - } - } -} - -bool LLGLSLShader::readProfileQuery(bool for_runtime, bool force_read) -{ - if (sProfileEnabled || for_runtime) - { - if (!mProfilePending) - { - glEndQuery(GL_TIME_ELAPSED); - if (!for_runtime) - { - glEndQuery(GL_SAMPLES_PASSED); - glEndQuery(GL_PRIMITIVES_GENERATED); - } - mProfilePending = for_runtime; - } - - if (mProfilePending && for_runtime && !force_read) - { - GLuint64 result = 0; - glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT_AVAILABLE, &result); - - if (result != GL_TRUE) - { - return false; - } - } - - GLuint64 time_elapsed = 0; - glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT, &time_elapsed); - mTimeElapsed += time_elapsed; - mProfilePending = false; - - if (!for_runtime) - { - GLuint64 samples_passed = 0; - glGetQueryObjectui64v(mSamplesQuery, GL_QUERY_RESULT, &samples_passed); - - U64 primitives_generated = 0; - glGetQueryObjectui64v(mPrimitivesQuery, GL_QUERY_RESULT, &primitives_generated); - sTotalTimeElapsed += time_elapsed; - - sTotalSamplesDrawn += samples_passed; - mSamplesDrawn += samples_passed; - - U32 tri_count = (U32)primitives_generated / 3; - - mTrianglesDrawn += tri_count; - sTotalTrianglesDrawn += tri_count; - - sTotalBinds++; - mBinds++; - } - } - - return true; -} - - - -LLGLSLShader::LLGLSLShader() - : mProgramObject(0), - mAttributeMask(0), - mTotalUniformSize(0), - mActiveTextureChannels(0), - mShaderLevel(0), - mShaderGroup(SG_DEFAULT), - mFeatures(), - mUniformsDirty(false), - mTimerQuery(0), - mSamplesQuery(0), - mPrimitivesQuery(0) -{ - -} - -LLGLSLShader::~LLGLSLShader() -{ -} - -void LLGLSLShader::unload() -{ - mShaderFiles.clear(); - mDefines.clear(); - mFeatures = LLShaderFeatures(); - - unloadInternal(); -} - -void LLGLSLShader::unloadInternal() -{ - sInstances.erase(this); - - stop_glerror(); - mAttribute.clear(); - mTexture.clear(); - mUniform.clear(); - - if (mProgramObject) - { - GLuint obj[1024]; - GLsizei count = 0; - glGetAttachedShaders(mProgramObject, 1024, &count, obj); - - for (GLsizei i = 0; i < count; i++) - { - glDetachShader(mProgramObject, obj[i]); - } - - for (GLsizei i = 0; i < count; i++) - { - if (glIsShader(obj[i])) - { - glDeleteShader(obj[i]); - } - } - - glDeleteProgram(mProgramObject); - - mProgramObject = 0; - } - - if (mTimerQuery) - { - glDeleteQueries(1, &mTimerQuery); - mTimerQuery = 0; - } - - if (mSamplesQuery) - { - glDeleteQueries(1, &mSamplesQuery); - mSamplesQuery = 0; - } - - //hack to make apple not complain - glGetError(); - - stop_glerror(); -} - -bool LLGLSLShader::createShader(std::vector* attributes, - std::vector* uniforms, - U32 varying_count, - const char** varyings) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - unloadInternal(); - - sInstances.insert(this); - - //reloading, reset matrix hash values - for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i) - { - mMatHash[i] = 0xFFFFFFFF; - } - mLightHash = 0xFFFFFFFF; - - llassert_always(!mShaderFiles.empty()); - -#if LL_DARWIN - // work-around missing mix(vec3,vec3,bvec3) - mDefines["OLD_SELECT"] = "1"; -#endif - - mShaderHash = hash(); - - // Create program - mProgramObject = glCreateProgram(); - if (mProgramObject == 0) - { - // Shouldn't happen if shader related extensions, like ARB_vertex_shader, exist. - LL_SHADER_LOADING_WARNS() << "Failed to create handle for shader: " << mName << LL_ENDL; - unloadInternal(); - return false; - } - - bool success = true; - - mUsingBinaryProgram = LLShaderMgr::instance()->loadCachedProgramBinary(this); - - if (!mUsingBinaryProgram) - { -#if DEBUG_SHADER_INCLUDES - fprintf(stderr, "--- %s ---\n", mName.c_str()); -#endif // DEBUG_SHADER_INCLUDES - - //compile new source - vector< pair >::iterator fileIter = mShaderFiles.begin(); - for (; fileIter != mShaderFiles.end(); fileIter++) - { - GLuint shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, &mDefines, mFeatures.mIndexedTextureChannels); - LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL; - if (shaderhandle) - { - attachObject(shaderhandle); - } - else - { - success = false; - } - } - } - - // Attach existing objects - if (!LLShaderMgr::instance()->attachShaderFeatures(this)) - { - unloadInternal(); - return false; - } - // Map attributes and uniforms - if (success) - { - success = mapAttributes(attributes); - } - if (success) - { - success = mapUniforms(uniforms); - } - if (!success) - { - LL_SHADER_LOADING_WARNS() << "Failed to link shader: " << mName << LL_ENDL; - - // Try again using a lower shader level; - if (mShaderLevel > 0) - { - LL_SHADER_LOADING_WARNS() << "Failed to link using shader level " << mShaderLevel << " trying again using shader level " << (mShaderLevel - 1) << LL_ENDL; - mShaderLevel--; - return createShader(attributes, uniforms); - } - else - { - // Give up and unload shader. - unloadInternal(); - } - } - else if (mFeatures.mIndexedTextureChannels > 0) - { //override texture channels for indexed texture rendering - bind(); - S32 channel_count = mFeatures.mIndexedTextureChannels; - - for (S32 i = 0; i < channel_count; i++) - { - LLStaticHashedString uniName(llformat("tex%d", i)); - uniform1i(uniName, i); - } - - S32 cur_tex = channel_count; //adjust any texture channels that might have been overwritten - for (U32 i = 0; i < mTexture.size(); i++) - { - if (mTexture[i] > -1 && mTexture[i] < channel_count) - { - llassert(cur_tex < gGLManager.mNumTextureImageUnits); - uniform1i(i, cur_tex); - mTexture[i] = cur_tex++; - } - } - unbind(); - } - -#ifdef LL_PROFILER_ENABLE_RENDER_DOC - setLabel(mName.c_str()); -#endif - - return success; -} - -#if DEBUG_SHADER_INCLUDES -void dumpAttachObject(const char* func_name, GLuint program_object, const std::string& object_path) -{ - GLchar* info_log; - GLint info_len_expect = 0; - GLint info_len_actual = 0; - - glGetShaderiv(program_object, GL_INFO_LOG_LENGTH, , &info_len_expect); - fprintf(stderr, " * %-20s(), log size: %d, %s\n", func_name, info_len_expect, object_path.c_str()); - - if (info_len_expect > 0) - { - fprintf(stderr, " ========== %s() ========== \n", func_name); - info_log = new GLchar[info_len_expect]; - glGetProgramInfoLog(program_object, info_len_expect, &info_len_actual, info_log); - fprintf(stderr, "%s\n", info_log); - delete[] info_log; - } -} -#endif // DEBUG_SHADER_INCLUDES - -bool LLGLSLShader::attachVertexObject(std::string object_path) -{ - if (LLShaderMgr::instance()->mVertexShaderObjects.count(object_path) > 0) - { - stop_glerror(); - glAttachShader(mProgramObject, LLShaderMgr::instance()->mVertexShaderObjects[object_path]); -#if DEBUG_SHADER_INCLUDES - dumpAttachObject("attachVertexObject", mProgramObject, object_path); -#endif // DEBUG_SHADER_INCLUDES - stop_glerror(); - return true; - } - else - { - LL_SHADER_LOADING_WARNS() << "Attempting to attach shader object: '" << object_path << "' that hasn't been compiled." << LL_ENDL; - return false; - } -} - -bool LLGLSLShader::attachFragmentObject(std::string object_path) -{ - if(mUsingBinaryProgram) - return true; - - if (LLShaderMgr::instance()->mFragmentShaderObjects.count(object_path) > 0) - { - stop_glerror(); - glAttachShader(mProgramObject, LLShaderMgr::instance()->mFragmentShaderObjects[object_path]); -#if DEBUG_SHADER_INCLUDES - dumpAttachObject("attachFragmentObject", mProgramObject, object_path); -#endif // DEBUG_SHADER_INCLUDES - stop_glerror(); - return true; - } - else - { - LL_SHADER_LOADING_WARNS() << "Attempting to attach shader object: '" << object_path << "' that hasn't been compiled." << LL_ENDL; - return false; - } -} - -void LLGLSLShader::attachObject(GLuint object) -{ - if(mUsingBinaryProgram) - return; - - if (object != 0) - { - stop_glerror(); - glAttachShader(mProgramObject, object); -#if DEBUG_SHADER_INCLUDES - std::string object_path("???"); - dumpAttachObject("attachObject", mProgramObject, object_path); -#endif // DEBUG_SHADER_INCLUDES - stop_glerror(); - } - else - { - LL_SHADER_LOADING_WARNS() << "Attempting to attach non existing shader object. " << LL_ENDL; - } -} - -void LLGLSLShader::attachObjects(GLuint* objects, S32 count) -{ - if(mUsingBinaryProgram) - return; - - for (S32 i = 0; i < count; i++) - { - attachObject(objects[i]); - } -} - -bool LLGLSLShader::mapAttributes(const std::vector* attributes) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - bool res = true; - if (!mUsingBinaryProgram) - { - //before linking, make sure reserved attributes always have consistent locations - for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++) - { - const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str(); - glBindAttribLocation(mProgramObject, i, (const GLchar*)name); - } - - //link the program - res = link(); - } - - mAttribute.clear(); - U32 numAttributes = (attributes == NULL) ? 0 : attributes->size(); -#if LL_RELEASE_WITH_DEBUG_INFO - mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, { -1, NULL }); -#else - mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, -1); -#endif - - if (res) - { //read back channel locations - - mAttributeMask = 0; - - //read back reserved channels first - for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++) - { - const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str(); - S32 index = glGetAttribLocation(mProgramObject, (const GLchar*)name); - if (index != -1) - { -#if LL_RELEASE_WITH_DEBUG_INFO - mAttribute[i] = { index, name }; -#else - mAttribute[i] = index; -#endif - mAttributeMask |= 1 << i; - LL_DEBUGS("ShaderUniform") << "Attribute " << name << " assigned to channel " << index << LL_ENDL; - } - } - if (attributes != NULL) - { - for (U32 i = 0; i < numAttributes; i++) - { - const char* name = (*attributes)[i].String().c_str(); - S32 index = glGetAttribLocation(mProgramObject, name); - if (index != -1) - { - mAttribute[LLShaderMgr::instance()->mReservedAttribs.size() + i] = index; - LL_DEBUGS("ShaderUniform") << "Attribute " << name << " assigned to channel " << index << LL_ENDL; - } - } - } - - return true; - } - - return false; -} - -void LLGLSLShader::mapUniform(GLint index, const vector* uniforms) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - if (index == -1) - { - return; - } - - GLenum type; - GLsizei length; - GLint size = -1; - char name[1024]; /* Flawfinder: ignore */ - name[0] = 0; - - - glGetActiveUniform(mProgramObject, index, 1024, &length, &size, &type, (GLchar*)name); - if (size > 0) - { - switch (type) - { - case GL_FLOAT_VEC2: size *= 2; break; - case GL_FLOAT_VEC3: size *= 3; break; - case GL_FLOAT_VEC4: size *= 4; break; - case GL_DOUBLE: size *= 2; break; - case GL_DOUBLE_VEC2: size *= 2; break; - case GL_DOUBLE_VEC3: size *= 6; break; - case GL_DOUBLE_VEC4: size *= 8; break; - case GL_INT_VEC2: size *= 2; break; - case GL_INT_VEC3: size *= 3; break; - case GL_INT_VEC4: size *= 4; break; - case GL_UNSIGNED_INT_VEC2: size *= 2; break; - case GL_UNSIGNED_INT_VEC3: size *= 3; break; - case GL_UNSIGNED_INT_VEC4: size *= 4; break; - case GL_BOOL_VEC2: size *= 2; break; - case GL_BOOL_VEC3: size *= 3; break; - case GL_BOOL_VEC4: size *= 4; break; - case GL_FLOAT_MAT2: size *= 4; break; - case GL_FLOAT_MAT3: size *= 9; break; - case GL_FLOAT_MAT4: size *= 16; break; - case GL_FLOAT_MAT2x3: size *= 6; break; - case GL_FLOAT_MAT2x4: size *= 8; break; - case GL_FLOAT_MAT3x2: size *= 6; break; - case GL_FLOAT_MAT3x4: size *= 12; break; - case GL_FLOAT_MAT4x2: size *= 8; break; - case GL_FLOAT_MAT4x3: size *= 12; break; - case GL_DOUBLE_MAT2: size *= 8; break; - case GL_DOUBLE_MAT3: size *= 18; break; - case GL_DOUBLE_MAT4: size *= 32; break; - case GL_DOUBLE_MAT2x3: size *= 12; break; - case GL_DOUBLE_MAT2x4: size *= 16; break; - case GL_DOUBLE_MAT3x2: size *= 12; break; - case GL_DOUBLE_MAT3x4: size *= 24; break; - case GL_DOUBLE_MAT4x2: size *= 16; break; - case GL_DOUBLE_MAT4x3: size *= 24; break; - } - mTotalUniformSize += size; - } - - S32 location = glGetUniformLocation(mProgramObject, name); - if (location != -1) - { - //chop off "[0]" so we can always access the first element - //of an array by the array name - char* is_array = strstr(name, "[0]"); - if (is_array) - { - is_array[0] = 0; - } - - LLStaticHashedString hashedName(name); - mUniformMap[hashedName] = location; - - LL_DEBUGS("ShaderUniform") << "Uniform " << name << " is at location " << location << LL_ENDL; - - //find the index of this uniform - for (S32 i = 0; i < (S32)LLShaderMgr::instance()->mReservedUniforms.size(); i++) - { - if ((mUniform[i] == -1) - && (LLShaderMgr::instance()->mReservedUniforms[i] == name)) - { - //found it - mUniform[i] = location; - mTexture[i] = mapUniformTextureChannel(location, type, size); - return; - } - } - - if (uniforms != NULL) - { - for (U32 i = 0; i < uniforms->size(); i++) - { - if ((mUniform[i + LLShaderMgr::instance()->mReservedUniforms.size()] == -1) - && ((*uniforms)[i].String() == name)) - { - //found it - mUniform[i + LLShaderMgr::instance()->mReservedUniforms.size()] = location; - mTexture[i + LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type, size); - return; - } - } - } - } -} - -void LLGLSLShader::clearPermutations() -{ - mDefines.clear(); -} - -void LLGLSLShader::addPermutation(std::string name, std::string value) -{ - mDefines[name] = value; -} - -void LLGLSLShader::addConstant(const LLGLSLShader::eShaderConsts shader_const) -{ - addPermutation(gShaderConstsKey[shader_const], gShaderConstsVal[shader_const]); -} - -void LLGLSLShader::removePermutation(std::string name) -{ - mDefines.erase(name); -} - -GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type, GLint size) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - if ((type >= GL_SAMPLER_1D && type <= GL_SAMPLER_2D_RECT_SHADOW) || - type == GL_SAMPLER_2D_MULTISAMPLE || - type == GL_SAMPLER_CUBE_MAP_ARRAY) - { //this here is a texture - GLint ret = mActiveTextureChannels; - if (size == 1) - { - glUniform1i(location, mActiveTextureChannels); - LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL; - mActiveTextureChannels++; - } - else - { - //is array of textures, make sequential after this texture - GLint channel[32]; // <=== only support up to 32 texture channels - llassert(size <= 32); - size = llmin(size, 32); - for (int i = 0; i < size; ++i) - { - channel[i] = mActiveTextureChannels++; - } - glUniform1iv(location, size, channel); - LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << - (mActiveTextureChannels - size) << " through " << (mActiveTextureChannels - 1) << LL_ENDL; - } - - llassert(mActiveTextureChannels <= 32); // too many textures (probably) - return ret; - } - return -1; -} - -bool LLGLSLShader::mapUniforms(const vector* uniforms) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - bool res = true; - - mTotalUniformSize = 0; - mActiveTextureChannels = 0; - mUniform.clear(); - mUniformMap.clear(); - mTexture.clear(); - mValue.clear(); - //initialize arrays - U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size(); - mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); - mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); - - bind(); - - //get the number of active uniforms - GLint activeCount; - glGetProgramiv(mProgramObject, GL_ACTIVE_UNIFORMS, &activeCount); - - //........................................................................................................................................ - //........................................................................................ - - /* - EXPLANATION: - This is part of code is temporary because as the final result the mapUniform() should be rewrited. - But it's a huge a volume of work which is need to be a more carefully performed for avoid possible - regression's (i.e. it should be formalized a separate ticket in JIRA). - - RESON: - The reason of this code is that SL engine is very sensitive to fact that "diffuseMap" should be appear - first as uniform parameter which is should get 0-"texture channel" index (see mapUniformTextureChannel() and mActiveTextureChannels) - it influence to which is texture matrix will be updated during rendering. - - But, order of indexe's of uniform variables is not defined and GLSL compiler can change it as want - , even if the "diffuseMap" will be appear and use first in shader code. - - As example where this situation appear see: "Deferred Material Shader 28/29/30/31" - And tickets: MAINT-4165, MAINT-4839, MAINT-3568, MAINT-6437 - - --- davep TODO -- pretty sure the entire block here is superstitious and that the uniform index has nothing to do with the texture channel - texture channel should follow the uniform VALUE - */ - - - S32 diffuseMap = glGetUniformLocation(mProgramObject, "diffuseMap"); - S32 specularMap = glGetUniformLocation(mProgramObject, "specularMap"); - S32 bumpMap = glGetUniformLocation(mProgramObject, "bumpMap"); - S32 altDiffuseMap = glGetUniformLocation(mProgramObject, "altDiffuseMap"); - S32 environmentMap = glGetUniformLocation(mProgramObject, "environmentMap"); - S32 reflectionMap = glGetUniformLocation(mProgramObject, "reflectionMap"); - - std::set skip_index; - - if (-1 != diffuseMap && (-1 != specularMap || -1 != bumpMap || -1 != environmentMap || -1 != altDiffuseMap)) - { - GLenum type; - GLsizei length; - GLint size = -1; - char name[1024]; - - diffuseMap = altDiffuseMap = specularMap = bumpMap = environmentMap = -1; - - for (S32 i = 0; i < activeCount; i++) - { - name[0] = '\0'; - - glGetActiveUniform(mProgramObject, i, 1024, &length, &size, &type, (GLchar*)name); - - if (-1 == diffuseMap && std::string(name) == "diffuseMap") - { - diffuseMap = i; - continue; - } - - if (-1 == specularMap && std::string(name) == "specularMap") - { - specularMap = i; - continue; - } - - if (-1 == bumpMap && std::string(name) == "bumpMap") - { - bumpMap = i; - continue; - } - - if (-1 == environmentMap && std::string(name) == "environmentMap") - { - environmentMap = i; - continue; - } - - if (-1 == reflectionMap && std::string(name) == "reflectionMap") - { - reflectionMap = i; - continue; - } - - if (-1 == altDiffuseMap && std::string(name) == "altDiffuseMap") - { - altDiffuseMap = i; - continue; - } - } - - bool specularDiff = specularMap < diffuseMap && -1 != specularMap; - bool bumpLessDiff = bumpMap < diffuseMap && -1 != bumpMap; - bool envLessDiff = environmentMap < diffuseMap && -1 != environmentMap; - bool refLessDiff = reflectionMap < diffuseMap && -1 != reflectionMap; - - if (specularDiff || bumpLessDiff || envLessDiff || refLessDiff) - { - mapUniform(diffuseMap, uniforms); - skip_index.insert(diffuseMap); - - if (-1 != specularMap) { - mapUniform(specularMap, uniforms); - skip_index.insert(specularMap); - } - - if (-1 != bumpMap) { - mapUniform(bumpMap, uniforms); - skip_index.insert(bumpMap); - } - - if (-1 != environmentMap) { - mapUniform(environmentMap, uniforms); - skip_index.insert(environmentMap); - } - - if (-1 != reflectionMap) { - mapUniform(reflectionMap, uniforms); - skip_index.insert(reflectionMap); - } - } - } - - //........................................................................................ - - for (S32 i = 0; i < activeCount; i++) - { - //........................................................................................ - if (skip_index.end() != skip_index.find(i)) continue; - //........................................................................................ - - mapUniform(i, uniforms); - } - //........................................................................................................................................ - - if (mFeatures.hasReflectionProbes) // Set up block binding, in a way supported by Apple (rather than binding = 1 in .glsl). - { // See slide 35 and more of https://docs.huihoo.com/apple/wwdc/2011/session_420__advances_in_opengl_for_mac_os_x_lion.pdf - static const GLuint BLOCKBINDING = 1; //picked by us - //Get the index, similar to a uniform location - GLuint UBOBlockIndex = glGetUniformBlockIndex(mProgramObject, "ReflectionProbes"); - if (UBOBlockIndex != GL_INVALID_INDEX) - { - //Set this index to a binding index - glUniformBlockBinding(mProgramObject, UBOBlockIndex, BLOCKBINDING); - } - } - unbind(); - - LL_DEBUGS("ShaderUniform") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL; - return res; -} - - -bool LLGLSLShader::link(bool suppress_errors) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - bool success = LLShaderMgr::instance()->linkProgramObject(mProgramObject, suppress_errors); - - if (!success && !suppress_errors) - { - LLShaderMgr::instance()->dumpObjectLog(mProgramObject, !success, mName); - } - - if (success) - { - LLShaderMgr::instance()->saveCachedProgramBinary(this); - } - - return success; -} - -void LLGLSLShader::bind() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - llassert(mProgramObject != 0); - - gGL.flush(); - - if (sCurBoundShader != mProgramObject) // Don't re-bind current shader - { - if (sCurBoundShaderPtr) - { - sCurBoundShaderPtr->readProfileQuery(); - } - LLVertexBuffer::unbind(); - glUseProgram(mProgramObject); - sCurBoundShader = mProgramObject; - sCurBoundShaderPtr = this; - placeProfileQuery(); - LLVertexBuffer::setupClientArrays(mAttributeMask); - } - - if (mUniformsDirty) - { - LLShaderMgr::instance()->updateShaderUniforms(this); - mUniformsDirty = false; - } -} - -void LLGLSLShader::bind(bool rigged) -{ - if (rigged) - { - llassert(mRiggedVariant); - mRiggedVariant->bind(); - } - else - { - bind(); - } -} - -void LLGLSLShader::unbind(void) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - gGL.flush(); - LLVertexBuffer::unbind(); - - if (sCurBoundShaderPtr) - { - sCurBoundShaderPtr->readProfileQuery(); - } - - glUseProgram(0); - sCurBoundShader = 0; - sCurBoundShaderPtr = NULL; -} - -S32 LLGLSLShader::bindTexture(const std::string& uniform, LLTexture* texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - S32 channel = 0; - channel = getUniformLocation(uniform); - - return bindTexture(channel, texture, mode, colorspace); -} - -S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - if (uniform < 0 || uniform >= (S32)mTexture.size()) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; - return -1; - } - - uniform = mTexture[uniform]; - - if (uniform > -1) - { - gGL.getTexUnit(uniform)->bindFast(texture); - gGL.getTexUnit(uniform)->setTextureColorSpace(colorspace); - } - - return uniform; -} - -S32 LLGLSLShader::bindTexture(S32 uniform, LLRenderTarget* texture, bool depth, LLTexUnit::eTextureFilterOptions mode, U32 index) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - if (uniform < 0 || uniform >= (S32)mTexture.size()) - { - return -1; - } - - uniform = getTextureChannel(uniform); - - if (uniform > -1) - { - if (depth) { - gGL.getTexUnit(uniform)->bind(texture, true); - } - else { - bool has_mips = mode == LLTexUnit::TFO_TRILINEAR || mode == LLTexUnit::TFO_ANISOTROPIC; - gGL.getTexUnit(uniform)->bindManual(texture->getUsage(), texture->getTexture(index), has_mips); - } - - gGL.getTexUnit(uniform)->setTextureFilteringOption(mode); - } - - return uniform; -} - -S32 LLGLSLShader::bindTexture(const std::string& uniform, LLRenderTarget* texture, bool depth, LLTexUnit::eTextureFilterOptions mode) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - S32 channel = 0; - channel = getUniformLocation(uniform); - - return bindTexture(channel, texture, depth, mode); -} - -S32 LLGLSLShader::unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - S32 channel = 0; - channel = getUniformLocation(uniform); - - return unbindTexture(channel); -} - -S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - if (uniform < 0 || uniform >= (S32)mTexture.size()) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; - return -1; - } - - uniform = mTexture[uniform]; - - if (uniform > -1) - { - gGL.getTexUnit(uniform)->unbindFast(mode); - } - - return uniform; -} - -S32 LLGLSLShader::getTextureChannel(S32 uniform) const -{ - return mTexture[uniform]; -} - -S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - if (uniform < 0 || uniform >= (S32)mTexture.size()) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; - return -1; - } - S32 index = mTexture[uniform]; - if (index != -1) - { - gGL.getTexUnit(index)->activate(); - gGL.getTexUnit(index)->enable(mode); - gGL.getTexUnit(index)->setTextureColorSpace(space); - } - return index; -} - -S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - if (uniform < 0 || uniform >= (S32)mTexture.size()) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; - return -1; - } - S32 index = mTexture[uniform]; - if (index != -1 && gGL.getTexUnit(index)->getCurrType() != LLTexUnit::TT_NONE) - { - if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode && gGL.getTexUnit(index)->getCurrColorSpace() != space) - { - if (gDebugSession) - { - gFailLog << "Texture channel " << index << " texture type corrupted." << std::endl; - ll_fail("LLGLSLShader::disableTexture failed"); - } - else - { - LL_ERRS() << "Texture channel " << index << " texture type corrupted." << LL_ENDL; - } - } - gGL.getTexUnit(index)->disable(); - } - return index; -} - -void LLGLSLShader::uniform1i(U32 index, GLint x) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - llassert(sCurBoundShaderPtr == this); - if (mProgramObject) - { - if (mUniform.size() <= index) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - const auto& iter = mValue.find(mUniform[index]); - if (iter == mValue.end() || iter->second.mV[0] != x) - { - glUniform1i(mUniform[index], x); - mValue[mUniform[index]] = LLVector4(x, 0.f, 0.f, 0.f); - } - } - } -} - -void LLGLSLShader::uniform1f(U32 index, GLfloat x) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - llassert(sCurBoundShaderPtr == this); - - if (mProgramObject) - { - if (mUniform.size() <= index) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - const auto& iter = mValue.find(mUniform[index]); - if (iter == mValue.end() || iter->second.mV[0] != x) - { - glUniform1f(mUniform[index], x); - mValue[mUniform[index]] = LLVector4(x, 0.f, 0.f, 0.f); - } - } - } -} - -void LLGLSLShader::fastUniform1f(U32 index, GLfloat x) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - llassert(sCurBoundShaderPtr == this); - llassert(mProgramObject); - llassert(mUniform.size() <= index); - llassert(mUniform[index] >= 0); - glUniform1f(mUniform[index], x); -} - -void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - llassert(sCurBoundShaderPtr == this); - - if (mProgramObject) - { - if (mUniform.size() <= index) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(x, y, 0.f, 0.f); - if (iter == mValue.end() || shouldChange(iter->second, vec)) - { - glUniform2f(mUniform[index], x, y); - mValue[mUniform[index]] = vec; - } - } - } -} - -void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - llassert(sCurBoundShaderPtr == this); - - if (mProgramObject) - { - if (mUniform.size() <= index) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(x, y, z, 0.f); - if (iter == mValue.end() || shouldChange(iter->second, vec)) - { - glUniform3f(mUniform[index], x, y, z); - mValue[mUniform[index]] = vec; - } - } - } -} - -void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - llassert(sCurBoundShaderPtr == this); - - if (mProgramObject) - { - if (mUniform.size() <= index) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(x, y, z, w); - if (iter == mValue.end() || shouldChange(iter->second, vec)) - { - glUniform4f(mUniform[index], x, y, z, w); - mValue[mUniform[index]] = vec; - } - } - } -} - -void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - llassert(sCurBoundShaderPtr == this); - - if (mProgramObject) - { - if (mUniform.size() <= index) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(v[0], 0.f, 0.f, 0.f); - if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) - { - glUniform1iv(mUniform[index], count, v); - mValue[mUniform[index]] = vec; - } - } - } -} - -void LLGLSLShader::uniform4iv(U32 index, U32 count, const GLint* v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - llassert(sCurBoundShaderPtr == this); - - if (mProgramObject) - { - if (mUniform.size() <= index) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(v[0], v[1], v[2], v[3]); - if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) - { - glUniform1iv(mUniform[index], count, v); - mValue[mUniform[index]] = vec; - } - } - } -} - - -void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - llassert(sCurBoundShaderPtr == this); - - if (mProgramObject) - { - if (mUniform.size() <= index) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(v[0], 0.f, 0.f, 0.f); - if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) - { - glUniform1fv(mUniform[index], count, v); - mValue[mUniform[index]] = vec; - } - } - } -} - -void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - llassert(sCurBoundShaderPtr == this); - - if (mProgramObject) - { - if (mUniform.size() <= index) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(v[0], v[1], 0.f, 0.f); - if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) - { - glUniform2fv(mUniform[index], count, v); - mValue[mUniform[index]] = vec; - } - } - } -} - -void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - llassert(sCurBoundShaderPtr == this); - - if (mProgramObject) - { - if (mUniform.size() <= index) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(v[0], v[1], v[2], 0.f); - if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) - { - glUniform3fv(mUniform[index], count, v); - mValue[mUniform[index]] = vec; - } - } - } -} - -void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - llassert(sCurBoundShaderPtr == this); - - if (mProgramObject) - { - if (mUniform.size() <= index) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(v[0], v[1], v[2], v[3]); - if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - glUniform4fv(mUniform[index], count, v); - mValue[mUniform[index]] = vec; - } - } - } -} - -void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - llassert(sCurBoundShaderPtr == this); - - if (mProgramObject) - { - if (mUniform.size() <= index) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - glUniformMatrix2fv(mUniform[index], count, transpose, v); - } - } -} - -void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - llassert(sCurBoundShaderPtr == this); - - if (mProgramObject) - { - if (mUniform.size() <= index) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - glUniformMatrix3fv(mUniform[index], count, transpose, v); - } - } -} - -void LLGLSLShader::uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - llassert(sCurBoundShaderPtr == this); - - if (mProgramObject) - { - if (mUniform.size() <= index) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - glUniformMatrix3x4fv(mUniform[index], count, transpose, v); - } - } -} - -void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - llassert(sCurBoundShaderPtr == this); - - if (mProgramObject) - { - if (mUniform.size() <= index) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - glUniformMatrix4fv(mUniform[index], count, transpose, v); - } - } -} - -GLint LLGLSLShader::getUniformLocation(const LLStaticHashedString& uniform) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - GLint ret = -1; - if (mProgramObject) - { - LLStaticStringTable::iterator iter = mUniformMap.find(uniform); - if (iter != mUniformMap.end()) - { - if (gDebugGL) - { - stop_glerror(); - if (iter->second != glGetUniformLocation(mProgramObject, uniform.String().c_str())) - { - LL_ERRS() << "Uniform does not match." << LL_ENDL; - } - stop_glerror(); - } - ret = iter->second; - } - } - - return ret; -} - -GLint LLGLSLShader::getUniformLocation(U32 index) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - GLint ret = -1; - if (mProgramObject) - { - if (index >= mUniform.size()) - { - LL_WARNS_ONCE("Shader") << "Uniform index " << index << " out of bounds " << (S32)mUniform.size() << LL_ENDL; - return ret; - } - return mUniform[index]; - } - - return ret; -} - -GLint LLGLSLShader::getAttribLocation(U32 attrib) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - - if (attrib < mAttribute.size()) - { - return mAttribute[attrib]; - } - else - { - return -1; - } -} - -void LLGLSLShader::uniform1i(const LLStaticHashedString& uniform, GLint v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - const auto& iter = mValue.find(location); - LLVector4 vec(v, 0.f, 0.f, 0.f); - if (iter == mValue.end() || shouldChange(iter->second, vec)) - { - glUniform1i(location, v); - mValue[location] = vec; - } - } -} - -void LLGLSLShader::uniform1iv(const LLStaticHashedString& uniform, U32 count, const GLint* v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - LLVector4 vec(v[0], 0, 0, 0); - const auto& iter = mValue.find(location); - if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - glUniform1iv(location, count, v); - mValue[location] = vec; - } - } -} - -void LLGLSLShader::uniform4iv(const LLStaticHashedString& uniform, U32 count, const GLint* v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - LLVector4 vec(v[0], v[1], v[2], v[3]); - const auto& iter = mValue.find(location); - if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - glUniform4iv(location, count, v); - mValue[location] = vec; - } - } -} - -void LLGLSLShader::uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - const auto& iter = mValue.find(location); - LLVector4 vec(i, j, 0.f, 0.f); - if (iter == mValue.end() || shouldChange(iter->second, vec)) - { - glUniform2i(location, i, j); - mValue[location] = vec; - } - } -} - - -void LLGLSLShader::uniform1f(const LLStaticHashedString& uniform, GLfloat v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - const auto& iter = mValue.find(location); - LLVector4 vec(v, 0.f, 0.f, 0.f); - if (iter == mValue.end() || shouldChange(iter->second, vec)) - { - glUniform1f(location, v); - mValue[location] = vec; - } - } -} - -void LLGLSLShader::uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - const auto& iter = mValue.find(location); - LLVector4 vec(x, y, 0.f, 0.f); - if (iter == mValue.end() || shouldChange(iter->second, vec)) - { - glUniform2f(location, x, y); - mValue[location] = vec; - } - } - -} - -void LLGLSLShader::uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - const auto& iter = mValue.find(location); - LLVector4 vec(x, y, z, 0.f); - if (iter == mValue.end() || shouldChange(iter->second, vec)) - { - glUniform3f(location, x, y, z); - mValue[location] = vec; - } - } -} - -void LLGLSLShader::uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - const auto& iter = mValue.find(location); - LLVector4 vec(v[0], 0.f, 0.f, 0.f); - if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) - { - glUniform1fv(location, count, v); - mValue[location] = vec; - } - } -} - -void LLGLSLShader::uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - const auto& iter = mValue.find(location); - LLVector4 vec(v[0], v[1], 0.f, 0.f); - if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) - { - glUniform2fv(location, count, v); - mValue[location] = vec; - } - } -} - -void LLGLSLShader::uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - const auto& iter = mValue.find(location); - LLVector4 vec(v[0], v[1], v[2], 0.f); - if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) - { - glUniform3fv(location, count, v); - mValue[location] = vec; - } - } -} - -void LLGLSLShader::uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - LLVector4 vec(v); - const auto& iter = mValue.find(location); - if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - glUniform4fv(location, count, v); - mValue[location] = vec; - } - } -} - -void LLGLSLShader::uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat* v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - stop_glerror(); - glUniformMatrix4fv(location, count, transpose, v); - stop_glerror(); - } -} - - -void LLGLSLShader::vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) -{ - if (mAttribute[index] > 0) - { - glVertexAttrib4f(mAttribute[index], x, y, z, w); - } -} - -void LLGLSLShader::vertexAttrib4fv(U32 index, GLfloat* v) -{ - if (mAttribute[index] > 0) - { - glVertexAttrib4fv(mAttribute[index], v); - } -} - -void LLGLSLShader::setMinimumAlpha(F32 minimum) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - gGL.flush(); - uniform1f(LLShaderMgr::MINIMUM_ALPHA, minimum); -} - -void LLShaderUniforms::apply(LLGLSLShader* shader) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - for (auto& uniform : mIntegers) - { - shader->uniform1i(uniform.mUniform, uniform.mValue); - } - - for (auto& uniform : mFloats) - { - shader->uniform1f(uniform.mUniform, uniform.mValue); - } - - for (auto& uniform : mVectors) - { - shader->uniform4fv(uniform.mUniform, 1, uniform.mValue.mV); - } - - for (auto& uniform : mVector3s) - { - shader->uniform3fv(uniform.mUniform, 1, uniform.mValue.mV); - } -} - -LLUUID LLGLSLShader::hash() -{ - HBXXH128 hash_obj; - hash_obj.update(mName); - hash_obj.update(&mShaderGroup, sizeof(mShaderGroup)); - hash_obj.update(&mShaderLevel, sizeof(mShaderLevel)); - for (const auto& shdr_pair : mShaderFiles) - { - hash_obj.update(shdr_pair.first); - hash_obj.update(&shdr_pair.second, sizeof(GLenum)); - } - for (const auto& define_pair : mDefines) - { - hash_obj.update(define_pair.first); - hash_obj.update(define_pair.second); - - } - for (const auto& define_pair : LLGLSLShader::sGlobalDefines) - { - hash_obj.update(define_pair.first); - hash_obj.update(define_pair.second); - - } - hash_obj.update(&mFeatures, sizeof(LLShaderFeatures)); - hash_obj.update(gGLManager.mGLVendor); - hash_obj.update(gGLManager.mGLRenderer); - hash_obj.update(gGLManager.mGLVersionString); - return hash_obj.digest(); -} - -#ifdef LL_PROFILER_ENABLE_RENDER_DOC -void LLGLSLShader::setLabel(const char* label) { - LL_LABEL_OBJECT_GL(GL_PROGRAM, mProgramObject, strlen(label), label); -} -#endif +/** + * @file llglslshader.cpp + * @brief GLSL helper functions and state. + * + * $LicenseInfo:firstyear=2005&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llglslshader.h" + +#include "llshadermgr.h" +#include "llfile.h" +#include "llrender.h" +#include "llvertexbuffer.h" +#include "llrendertarget.h" + +#include "hbxxh.h" +#include "llsdserialize.h" + +#if LL_DARWIN +#include "OpenGL/OpenGL.h" +#endif + + // Print-print list of shader included source files that are linked together via glAttachShader() + // i.e. On macOS / OSX the AMD GLSL linker will display an error if a varying is left in an undefined state. +#define DEBUG_SHADER_INCLUDES 0 + +// Lots of STL stuff in here, using namespace std to keep things more readable +using std::vector; +using std::pair; +using std::make_pair; +using std::string; + +GLuint LLGLSLShader::sCurBoundShader = 0; +LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL; +S32 LLGLSLShader::sIndexedTextureChannels = 0; +bool LLGLSLShader::sProfileEnabled = false; +std::set LLGLSLShader::sInstances; +LLGLSLShader::defines_map_t LLGLSLShader::sGlobalDefines; +U64 LLGLSLShader::sTotalTimeElapsed = 0; +U32 LLGLSLShader::sTotalTrianglesDrawn = 0; +U64 LLGLSLShader::sTotalSamplesDrawn = 0; +U32 LLGLSLShader::sTotalBinds = 0; + +//UI shader -- declared here so llui_libtest will link properly +LLGLSLShader gUIProgram; +LLGLSLShader gSolidColorProgram; + +// NOTE: Keep gShaderConsts* and LLGLSLShader::ShaderConsts_e in sync! +const std::string gShaderConstsKey[LLGLSLShader::NUM_SHADER_CONSTS] = +{ + "LL_SHADER_CONST_CLOUD_MOON_DEPTH" + , "LL_SHADER_CONST_STAR_DEPTH" +}; + +// NOTE: Keep gShaderConsts* and LLGLSLShader::ShaderConsts_e in sync! +const std::string gShaderConstsVal[LLGLSLShader::NUM_SHADER_CONSTS] = +{ + "0.99998" // SHADER_CONST_CLOUD_MOON_DEPTH // SL-14113 + , "0.99999" // SHADER_CONST_STAR_DEPTH // SL-14113 +}; + + +bool shouldChange(const LLVector4& v1, const LLVector4& v2) +{ + return v1 != v2; +} + +//=============================== +// LLGLSL Shader implementation +//=============================== + +//static +void LLGLSLShader::initProfile() +{ + sProfileEnabled = true; + sTotalTimeElapsed = 0; + sTotalTrianglesDrawn = 0; + sTotalSamplesDrawn = 0; + sTotalBinds = 0; + + for (std::set::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) + { + (*iter)->clearStats(); + } +} + + +struct LLGLSLShaderCompareTimeElapsed +{ + bool operator()(const LLGLSLShader* const& lhs, const LLGLSLShader* const& rhs) + { + return lhs->mTimeElapsed < rhs->mTimeElapsed; + } +}; + +//static +void LLGLSLShader::finishProfile(bool emit_report) +{ + sProfileEnabled = false; + + if (emit_report) + { + std::vector sorted; + + for (std::set::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) + { + sorted.push_back(*iter); + } + + std::sort(sorted.begin(), sorted.end(), LLGLSLShaderCompareTimeElapsed()); + + bool unbound = false; + for (std::vector::iterator iter = sorted.begin(); iter != sorted.end(); ++iter) + { + (*iter)->dumpStats(); + if ((*iter)->mBinds == 0) + { + unbound = true; + } + } + + LL_INFOS() << "-----------------------------------" << LL_ENDL; + LL_INFOS() << "Total rendering time: " << llformat("%.4f ms", sTotalTimeElapsed / 1000000.f) << LL_ENDL; + LL_INFOS() << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn / 1000000.f) << LL_ENDL; + LL_INFOS() << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn / 1000000.f) << LL_ENDL; + LL_INFOS() << "-----------------------------------" << LL_ENDL; + + if (unbound) + { + LL_INFOS() << "The following shaders were unused: " << LL_ENDL; + for (std::vector::iterator iter = sorted.begin(); iter != sorted.end(); ++iter) + { + if ((*iter)->mBinds == 0) + { + LL_INFOS() << (*iter)->mName << LL_ENDL; + } + } + } + } +} + +void LLGLSLShader::clearStats() +{ + mTrianglesDrawn = 0; + mTimeElapsed = 0; + mSamplesDrawn = 0; + mBinds = 0; +} + +void LLGLSLShader::dumpStats() +{ + if (mBinds > 0) + { + LL_INFOS() << "=============================================" << LL_ENDL; + LL_INFOS() << mName << LL_ENDL; + for (U32 i = 0; i < mShaderFiles.size(); ++i) + { + LL_INFOS() << mShaderFiles[i].first << LL_ENDL; + } + LL_INFOS() << "=============================================" << LL_ENDL; + + F32 ms = mTimeElapsed / 1000000.f; + F32 seconds = ms / 1000.f; + + F32 pct_tris = (F32)mTrianglesDrawn / (F32)sTotalTrianglesDrawn * 100.f; + F32 tris_sec = (F32)(mTrianglesDrawn / 1000000.0); + tris_sec /= seconds; + + F32 pct_samples = (F32)((F64)mSamplesDrawn / (F64)sTotalSamplesDrawn) * 100.f; + F32 samples_sec = (F32)mSamplesDrawn / 1000000000.0; + samples_sec /= seconds; + + F32 pct_binds = (F32)mBinds / (F32)sTotalBinds * 100.f; + + LL_INFOS() << "Triangles Drawn: " << mTrianglesDrawn << " " << llformat("(%.2f pct of total, %.3f million/sec)", pct_tris, tris_sec) << LL_ENDL; + LL_INFOS() << "Binds: " << mBinds << " " << llformat("(%.2f pct of total)", pct_binds) << LL_ENDL; + LL_INFOS() << "SamplesDrawn: " << mSamplesDrawn << " " << llformat("(%.2f pct of total, %.3f billion/sec)", pct_samples, samples_sec) << LL_ENDL; + LL_INFOS() << "Time Elapsed: " << mTimeElapsed << " " << llformat("(%.2f pct of total, %.5f ms)\n", (F32)((F64)mTimeElapsed / (F64)sTotalTimeElapsed) * 100.f, ms) << LL_ENDL; + } +} + +//static +void LLGLSLShader::startProfile() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + if (sProfileEnabled && sCurBoundShaderPtr) + { + sCurBoundShaderPtr->placeProfileQuery(); + } + +} + +//static +void LLGLSLShader::stopProfile() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + if (sProfileEnabled && sCurBoundShaderPtr) + { + sCurBoundShaderPtr->unbind(); + } +} + +void LLGLSLShader::placeProfileQuery(bool for_runtime) +{ + if (sProfileEnabled || for_runtime) + { + if (mTimerQuery == 0) + { + glGenQueries(1, &mSamplesQuery); + glGenQueries(1, &mTimerQuery); + glGenQueries(1, &mPrimitivesQuery); + } + + glBeginQuery(GL_TIME_ELAPSED, mTimerQuery); + + if (!for_runtime) + { + glBeginQuery(GL_SAMPLES_PASSED, mSamplesQuery); + glBeginQuery(GL_PRIMITIVES_GENERATED, mPrimitivesQuery); + } + } +} + +bool LLGLSLShader::readProfileQuery(bool for_runtime, bool force_read) +{ + if (sProfileEnabled || for_runtime) + { + if (!mProfilePending) + { + glEndQuery(GL_TIME_ELAPSED); + if (!for_runtime) + { + glEndQuery(GL_SAMPLES_PASSED); + glEndQuery(GL_PRIMITIVES_GENERATED); + } + mProfilePending = for_runtime; + } + + if (mProfilePending && for_runtime && !force_read) + { + GLuint64 result = 0; + glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT_AVAILABLE, &result); + + if (result != GL_TRUE) + { + return false; + } + } + + GLuint64 time_elapsed = 0; + glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT, &time_elapsed); + mTimeElapsed += time_elapsed; + mProfilePending = false; + + if (!for_runtime) + { + GLuint64 samples_passed = 0; + glGetQueryObjectui64v(mSamplesQuery, GL_QUERY_RESULT, &samples_passed); + + U64 primitives_generated = 0; + glGetQueryObjectui64v(mPrimitivesQuery, GL_QUERY_RESULT, &primitives_generated); + sTotalTimeElapsed += time_elapsed; + + sTotalSamplesDrawn += samples_passed; + mSamplesDrawn += samples_passed; + + U32 tri_count = (U32)primitives_generated / 3; + + mTrianglesDrawn += tri_count; + sTotalTrianglesDrawn += tri_count; + + sTotalBinds++; + mBinds++; + } + } + + return true; +} + + + +LLGLSLShader::LLGLSLShader() + : mProgramObject(0), + mAttributeMask(0), + mTotalUniformSize(0), + mActiveTextureChannels(0), + mShaderLevel(0), + mShaderGroup(SG_DEFAULT), + mFeatures(), + mUniformsDirty(false), + mTimerQuery(0), + mSamplesQuery(0), + mPrimitivesQuery(0) +{ + +} + +LLGLSLShader::~LLGLSLShader() +{ +} + +void LLGLSLShader::unload() +{ + mShaderFiles.clear(); + mDefines.clear(); + mFeatures = LLShaderFeatures(); + + unloadInternal(); +} + +void LLGLSLShader::unloadInternal() +{ + sInstances.erase(this); + + stop_glerror(); + mAttribute.clear(); + mTexture.clear(); + mUniform.clear(); + + if (mProgramObject) + { + GLuint obj[1024]; + GLsizei count = 0; + glGetAttachedShaders(mProgramObject, 1024, &count, obj); + + for (GLsizei i = 0; i < count; i++) + { + glDetachShader(mProgramObject, obj[i]); + } + + for (GLsizei i = 0; i < count; i++) + { + if (glIsShader(obj[i])) + { + glDeleteShader(obj[i]); + } + } + + glDeleteProgram(mProgramObject); + + mProgramObject = 0; + } + + if (mTimerQuery) + { + glDeleteQueries(1, &mTimerQuery); + mTimerQuery = 0; + } + + if (mSamplesQuery) + { + glDeleteQueries(1, &mSamplesQuery); + mSamplesQuery = 0; + } + + //hack to make apple not complain + glGetError(); + + stop_glerror(); +} + +bool LLGLSLShader::createShader(std::vector* attributes, + std::vector* uniforms, + U32 varying_count, + const char** varyings) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + unloadInternal(); + + sInstances.insert(this); + + //reloading, reset matrix hash values + for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i) + { + mMatHash[i] = 0xFFFFFFFF; + } + mLightHash = 0xFFFFFFFF; + + llassert_always(!mShaderFiles.empty()); + +#if LL_DARWIN + // work-around missing mix(vec3,vec3,bvec3) + mDefines["OLD_SELECT"] = "1"; +#endif + + mShaderHash = hash(); + + // Create program + mProgramObject = glCreateProgram(); + if (mProgramObject == 0) + { + // Shouldn't happen if shader related extensions, like ARB_vertex_shader, exist. + LL_SHADER_LOADING_WARNS() << "Failed to create handle for shader: " << mName << LL_ENDL; + unloadInternal(); + return false; + } + + bool success = true; + + mUsingBinaryProgram = LLShaderMgr::instance()->loadCachedProgramBinary(this); + + if (!mUsingBinaryProgram) + { +#if DEBUG_SHADER_INCLUDES + fprintf(stderr, "--- %s ---\n", mName.c_str()); +#endif // DEBUG_SHADER_INCLUDES + + //compile new source + vector< pair >::iterator fileIter = mShaderFiles.begin(); + for (; fileIter != mShaderFiles.end(); fileIter++) + { + GLuint shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, &mDefines, mFeatures.mIndexedTextureChannels); + LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL; + if (shaderhandle) + { + attachObject(shaderhandle); + } + else + { + success = false; + } + } + } + + // Attach existing objects + if (!LLShaderMgr::instance()->attachShaderFeatures(this)) + { + unloadInternal(); + return false; + } + // Map attributes and uniforms + if (success) + { + success = mapAttributes(attributes); + } + if (success) + { + success = mapUniforms(uniforms); + } + if (!success) + { + LL_SHADER_LOADING_WARNS() << "Failed to link shader: " << mName << LL_ENDL; + + // Try again using a lower shader level; + if (mShaderLevel > 0) + { + LL_SHADER_LOADING_WARNS() << "Failed to link using shader level " << mShaderLevel << " trying again using shader level " << (mShaderLevel - 1) << LL_ENDL; + mShaderLevel--; + return createShader(attributes, uniforms); + } + else + { + // Give up and unload shader. + unloadInternal(); + } + } + else if (mFeatures.mIndexedTextureChannels > 0) + { //override texture channels for indexed texture rendering + bind(); + S32 channel_count = mFeatures.mIndexedTextureChannels; + + for (S32 i = 0; i < channel_count; i++) + { + LLStaticHashedString uniName(llformat("tex%d", i)); + uniform1i(uniName, i); + } + + S32 cur_tex = channel_count; //adjust any texture channels that might have been overwritten + for (U32 i = 0; i < mTexture.size(); i++) + { + if (mTexture[i] > -1 && mTexture[i] < channel_count) + { + llassert(cur_tex < gGLManager.mNumTextureImageUnits); + uniform1i(i, cur_tex); + mTexture[i] = cur_tex++; + } + } + unbind(); + } + +#ifdef LL_PROFILER_ENABLE_RENDER_DOC + setLabel(mName.c_str()); +#endif + + return success; +} + +#if DEBUG_SHADER_INCLUDES +void dumpAttachObject(const char* func_name, GLuint program_object, const std::string& object_path) +{ + GLchar* info_log; + GLint info_len_expect = 0; + GLint info_len_actual = 0; + + glGetShaderiv(program_object, GL_INFO_LOG_LENGTH, , &info_len_expect); + fprintf(stderr, " * %-20s(), log size: %d, %s\n", func_name, info_len_expect, object_path.c_str()); + + if (info_len_expect > 0) + { + fprintf(stderr, " ========== %s() ========== \n", func_name); + info_log = new GLchar[info_len_expect]; + glGetProgramInfoLog(program_object, info_len_expect, &info_len_actual, info_log); + fprintf(stderr, "%s\n", info_log); + delete[] info_log; + } +} +#endif // DEBUG_SHADER_INCLUDES + +bool LLGLSLShader::attachVertexObject(std::string object_path) +{ + if (LLShaderMgr::instance()->mVertexShaderObjects.count(object_path) > 0) + { + stop_glerror(); + glAttachShader(mProgramObject, LLShaderMgr::instance()->mVertexShaderObjects[object_path]); +#if DEBUG_SHADER_INCLUDES + dumpAttachObject("attachVertexObject", mProgramObject, object_path); +#endif // DEBUG_SHADER_INCLUDES + stop_glerror(); + return true; + } + else + { + LL_SHADER_LOADING_WARNS() << "Attempting to attach shader object: '" << object_path << "' that hasn't been compiled." << LL_ENDL; + return false; + } +} + +bool LLGLSLShader::attachFragmentObject(std::string object_path) +{ + if(mUsingBinaryProgram) + return true; + + if (LLShaderMgr::instance()->mFragmentShaderObjects.count(object_path) > 0) + { + stop_glerror(); + glAttachShader(mProgramObject, LLShaderMgr::instance()->mFragmentShaderObjects[object_path]); +#if DEBUG_SHADER_INCLUDES + dumpAttachObject("attachFragmentObject", mProgramObject, object_path); +#endif // DEBUG_SHADER_INCLUDES + stop_glerror(); + return true; + } + else + { + LL_SHADER_LOADING_WARNS() << "Attempting to attach shader object: '" << object_path << "' that hasn't been compiled." << LL_ENDL; + return false; + } +} + +void LLGLSLShader::attachObject(GLuint object) +{ + if(mUsingBinaryProgram) + return; + + if (object != 0) + { + stop_glerror(); + glAttachShader(mProgramObject, object); +#if DEBUG_SHADER_INCLUDES + std::string object_path("???"); + dumpAttachObject("attachObject", mProgramObject, object_path); +#endif // DEBUG_SHADER_INCLUDES + stop_glerror(); + } + else + { + LL_SHADER_LOADING_WARNS() << "Attempting to attach non existing shader object. " << LL_ENDL; + } +} + +void LLGLSLShader::attachObjects(GLuint* objects, S32 count) +{ + if(mUsingBinaryProgram) + return; + + for (S32 i = 0; i < count; i++) + { + attachObject(objects[i]); + } +} + +bool LLGLSLShader::mapAttributes(const std::vector* attributes) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + bool res = true; + if (!mUsingBinaryProgram) + { + //before linking, make sure reserved attributes always have consistent locations + for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++) + { + const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str(); + glBindAttribLocation(mProgramObject, i, (const GLchar*)name); + } + + //link the program + res = link(); + } + + mAttribute.clear(); + U32 numAttributes = (attributes == NULL) ? 0 : attributes->size(); +#if LL_RELEASE_WITH_DEBUG_INFO + mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, { -1, NULL }); +#else + mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, -1); +#endif + + if (res) + { //read back channel locations + + mAttributeMask = 0; + + //read back reserved channels first + for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++) + { + const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str(); + S32 index = glGetAttribLocation(mProgramObject, (const GLchar*)name); + if (index != -1) + { +#if LL_RELEASE_WITH_DEBUG_INFO + mAttribute[i] = { index, name }; +#else + mAttribute[i] = index; +#endif + mAttributeMask |= 1 << i; + LL_DEBUGS("ShaderUniform") << "Attribute " << name << " assigned to channel " << index << LL_ENDL; + } + } + if (attributes != NULL) + { + for (U32 i = 0; i < numAttributes; i++) + { + const char* name = (*attributes)[i].String().c_str(); + S32 index = glGetAttribLocation(mProgramObject, name); + if (index != -1) + { + mAttribute[LLShaderMgr::instance()->mReservedAttribs.size() + i] = index; + LL_DEBUGS("ShaderUniform") << "Attribute " << name << " assigned to channel " << index << LL_ENDL; + } + } + } + + return true; + } + + return false; +} + +void LLGLSLShader::mapUniform(GLint index, const vector* uniforms) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + if (index == -1) + { + return; + } + + GLenum type; + GLsizei length; + GLint size = -1; + char name[1024]; /* Flawfinder: ignore */ + name[0] = 0; + + + glGetActiveUniform(mProgramObject, index, 1024, &length, &size, &type, (GLchar*)name); + if (size > 0) + { + switch (type) + { + case GL_FLOAT_VEC2: size *= 2; break; + case GL_FLOAT_VEC3: size *= 3; break; + case GL_FLOAT_VEC4: size *= 4; break; + case GL_DOUBLE: size *= 2; break; + case GL_DOUBLE_VEC2: size *= 2; break; + case GL_DOUBLE_VEC3: size *= 6; break; + case GL_DOUBLE_VEC4: size *= 8; break; + case GL_INT_VEC2: size *= 2; break; + case GL_INT_VEC3: size *= 3; break; + case GL_INT_VEC4: size *= 4; break; + case GL_UNSIGNED_INT_VEC2: size *= 2; break; + case GL_UNSIGNED_INT_VEC3: size *= 3; break; + case GL_UNSIGNED_INT_VEC4: size *= 4; break; + case GL_BOOL_VEC2: size *= 2; break; + case GL_BOOL_VEC3: size *= 3; break; + case GL_BOOL_VEC4: size *= 4; break; + case GL_FLOAT_MAT2: size *= 4; break; + case GL_FLOAT_MAT3: size *= 9; break; + case GL_FLOAT_MAT4: size *= 16; break; + case GL_FLOAT_MAT2x3: size *= 6; break; + case GL_FLOAT_MAT2x4: size *= 8; break; + case GL_FLOAT_MAT3x2: size *= 6; break; + case GL_FLOAT_MAT3x4: size *= 12; break; + case GL_FLOAT_MAT4x2: size *= 8; break; + case GL_FLOAT_MAT4x3: size *= 12; break; + case GL_DOUBLE_MAT2: size *= 8; break; + case GL_DOUBLE_MAT3: size *= 18; break; + case GL_DOUBLE_MAT4: size *= 32; break; + case GL_DOUBLE_MAT2x3: size *= 12; break; + case GL_DOUBLE_MAT2x4: size *= 16; break; + case GL_DOUBLE_MAT3x2: size *= 12; break; + case GL_DOUBLE_MAT3x4: size *= 24; break; + case GL_DOUBLE_MAT4x2: size *= 16; break; + case GL_DOUBLE_MAT4x3: size *= 24; break; + } + mTotalUniformSize += size; + } + + S32 location = glGetUniformLocation(mProgramObject, name); + if (location != -1) + { + //chop off "[0]" so we can always access the first element + //of an array by the array name + char* is_array = strstr(name, "[0]"); + if (is_array) + { + is_array[0] = 0; + } + + LLStaticHashedString hashedName(name); + mUniformMap[hashedName] = location; + + LL_DEBUGS("ShaderUniform") << "Uniform " << name << " is at location " << location << LL_ENDL; + + //find the index of this uniform + for (S32 i = 0; i < (S32)LLShaderMgr::instance()->mReservedUniforms.size(); i++) + { + if ((mUniform[i] == -1) + && (LLShaderMgr::instance()->mReservedUniforms[i] == name)) + { + //found it + mUniform[i] = location; + mTexture[i] = mapUniformTextureChannel(location, type, size); + return; + } + } + + if (uniforms != NULL) + { + for (U32 i = 0; i < uniforms->size(); i++) + { + if ((mUniform[i + LLShaderMgr::instance()->mReservedUniforms.size()] == -1) + && ((*uniforms)[i].String() == name)) + { + //found it + mUniform[i + LLShaderMgr::instance()->mReservedUniforms.size()] = location; + mTexture[i + LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type, size); + return; + } + } + } + } +} + +void LLGLSLShader::clearPermutations() +{ + mDefines.clear(); +} + +void LLGLSLShader::addPermutation(std::string name, std::string value) +{ + mDefines[name] = value; +} + +void LLGLSLShader::addConstant(const LLGLSLShader::eShaderConsts shader_const) +{ + addPermutation(gShaderConstsKey[shader_const], gShaderConstsVal[shader_const]); +} + +void LLGLSLShader::removePermutation(std::string name) +{ + mDefines.erase(name); +} + +GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type, GLint size) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + if ((type >= GL_SAMPLER_1D && type <= GL_SAMPLER_2D_RECT_SHADOW) || + type == GL_SAMPLER_2D_MULTISAMPLE || + type == GL_SAMPLER_CUBE_MAP_ARRAY) + { //this here is a texture + GLint ret = mActiveTextureChannels; + if (size == 1) + { + glUniform1i(location, mActiveTextureChannels); + LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL; + mActiveTextureChannels++; + } + else + { + //is array of textures, make sequential after this texture + GLint channel[32]; // <=== only support up to 32 texture channels + llassert(size <= 32); + size = llmin(size, 32); + for (int i = 0; i < size; ++i) + { + channel[i] = mActiveTextureChannels++; + } + glUniform1iv(location, size, channel); + LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << + (mActiveTextureChannels - size) << " through " << (mActiveTextureChannels - 1) << LL_ENDL; + } + + llassert(mActiveTextureChannels <= 32); // too many textures (probably) + return ret; + } + return -1; +} + +bool LLGLSLShader::mapUniforms(const vector* uniforms) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + bool res = true; + + mTotalUniformSize = 0; + mActiveTextureChannels = 0; + mUniform.clear(); + mUniformMap.clear(); + mTexture.clear(); + mValue.clear(); + //initialize arrays + U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size(); + mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); + mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); + + bind(); + + //get the number of active uniforms + GLint activeCount; + glGetProgramiv(mProgramObject, GL_ACTIVE_UNIFORMS, &activeCount); + + //........................................................................................................................................ + //........................................................................................ + + /* + EXPLANATION: + This is part of code is temporary because as the final result the mapUniform() should be rewrited. + But it's a huge a volume of work which is need to be a more carefully performed for avoid possible + regression's (i.e. it should be formalized a separate ticket in JIRA). + + RESON: + The reason of this code is that SL engine is very sensitive to fact that "diffuseMap" should be appear + first as uniform parameter which is should get 0-"texture channel" index (see mapUniformTextureChannel() and mActiveTextureChannels) + it influence to which is texture matrix will be updated during rendering. + + But, order of indexe's of uniform variables is not defined and GLSL compiler can change it as want + , even if the "diffuseMap" will be appear and use first in shader code. + + As example where this situation appear see: "Deferred Material Shader 28/29/30/31" + And tickets: MAINT-4165, MAINT-4839, MAINT-3568, MAINT-6437 + + --- davep TODO -- pretty sure the entire block here is superstitious and that the uniform index has nothing to do with the texture channel + texture channel should follow the uniform VALUE + */ + + + S32 diffuseMap = glGetUniformLocation(mProgramObject, "diffuseMap"); + S32 specularMap = glGetUniformLocation(mProgramObject, "specularMap"); + S32 bumpMap = glGetUniformLocation(mProgramObject, "bumpMap"); + S32 altDiffuseMap = glGetUniformLocation(mProgramObject, "altDiffuseMap"); + S32 environmentMap = glGetUniformLocation(mProgramObject, "environmentMap"); + S32 reflectionMap = glGetUniformLocation(mProgramObject, "reflectionMap"); + + std::set skip_index; + + if (-1 != diffuseMap && (-1 != specularMap || -1 != bumpMap || -1 != environmentMap || -1 != altDiffuseMap)) + { + GLenum type; + GLsizei length; + GLint size = -1; + char name[1024]; + + diffuseMap = altDiffuseMap = specularMap = bumpMap = environmentMap = -1; + + for (S32 i = 0; i < activeCount; i++) + { + name[0] = '\0'; + + glGetActiveUniform(mProgramObject, i, 1024, &length, &size, &type, (GLchar*)name); + + if (-1 == diffuseMap && std::string(name) == "diffuseMap") + { + diffuseMap = i; + continue; + } + + if (-1 == specularMap && std::string(name) == "specularMap") + { + specularMap = i; + continue; + } + + if (-1 == bumpMap && std::string(name) == "bumpMap") + { + bumpMap = i; + continue; + } + + if (-1 == environmentMap && std::string(name) == "environmentMap") + { + environmentMap = i; + continue; + } + + if (-1 == reflectionMap && std::string(name) == "reflectionMap") + { + reflectionMap = i; + continue; + } + + if (-1 == altDiffuseMap && std::string(name) == "altDiffuseMap") + { + altDiffuseMap = i; + continue; + } + } + + bool specularDiff = specularMap < diffuseMap && -1 != specularMap; + bool bumpLessDiff = bumpMap < diffuseMap && -1 != bumpMap; + bool envLessDiff = environmentMap < diffuseMap && -1 != environmentMap; + bool refLessDiff = reflectionMap < diffuseMap && -1 != reflectionMap; + + if (specularDiff || bumpLessDiff || envLessDiff || refLessDiff) + { + mapUniform(diffuseMap, uniforms); + skip_index.insert(diffuseMap); + + if (-1 != specularMap) { + mapUniform(specularMap, uniforms); + skip_index.insert(specularMap); + } + + if (-1 != bumpMap) { + mapUniform(bumpMap, uniforms); + skip_index.insert(bumpMap); + } + + if (-1 != environmentMap) { + mapUniform(environmentMap, uniforms); + skip_index.insert(environmentMap); + } + + if (-1 != reflectionMap) { + mapUniform(reflectionMap, uniforms); + skip_index.insert(reflectionMap); + } + } + } + + //........................................................................................ + + for (S32 i = 0; i < activeCount; i++) + { + //........................................................................................ + if (skip_index.end() != skip_index.find(i)) continue; + //........................................................................................ + + mapUniform(i, uniforms); + } + //........................................................................................................................................ + + if (mFeatures.hasReflectionProbes) // Set up block binding, in a way supported by Apple (rather than binding = 1 in .glsl). + { // See slide 35 and more of https://docs.huihoo.com/apple/wwdc/2011/session_420__advances_in_opengl_for_mac_os_x_lion.pdf + static const GLuint BLOCKBINDING = 1; //picked by us + //Get the index, similar to a uniform location + GLuint UBOBlockIndex = glGetUniformBlockIndex(mProgramObject, "ReflectionProbes"); + if (UBOBlockIndex != GL_INVALID_INDEX) + { + //Set this index to a binding index + glUniformBlockBinding(mProgramObject, UBOBlockIndex, BLOCKBINDING); + } + } + unbind(); + + LL_DEBUGS("ShaderUniform") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL; + return res; +} + + +bool LLGLSLShader::link(bool suppress_errors) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + bool success = LLShaderMgr::instance()->linkProgramObject(mProgramObject, suppress_errors); + + if (!success && !suppress_errors) + { + LLShaderMgr::instance()->dumpObjectLog(mProgramObject, !success, mName); + } + + if (success) + { + LLShaderMgr::instance()->saveCachedProgramBinary(this); + } + + return success; +} + +void LLGLSLShader::bind() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + llassert(mProgramObject != 0); + + gGL.flush(); + + if (sCurBoundShader != mProgramObject) // Don't re-bind current shader + { + if (sCurBoundShaderPtr) + { + sCurBoundShaderPtr->readProfileQuery(); + } + LLVertexBuffer::unbind(); + glUseProgram(mProgramObject); + sCurBoundShader = mProgramObject; + sCurBoundShaderPtr = this; + placeProfileQuery(); + LLVertexBuffer::setupClientArrays(mAttributeMask); + } + + if (mUniformsDirty) + { + LLShaderMgr::instance()->updateShaderUniforms(this); + mUniformsDirty = false; + } +} + +void LLGLSLShader::bind(bool rigged) +{ + if (rigged) + { + llassert(mRiggedVariant); + mRiggedVariant->bind(); + } + else + { + bind(); + } +} + +void LLGLSLShader::unbind(void) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + gGL.flush(); + LLVertexBuffer::unbind(); + + if (sCurBoundShaderPtr) + { + sCurBoundShaderPtr->readProfileQuery(); + } + + glUseProgram(0); + sCurBoundShader = 0; + sCurBoundShaderPtr = NULL; +} + +S32 LLGLSLShader::bindTexture(const std::string& uniform, LLTexture* texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + S32 channel = 0; + channel = getUniformLocation(uniform); + + return bindTexture(channel, texture, mode, colorspace); +} + +S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + if (uniform < 0 || uniform >= (S32)mTexture.size()) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; + return -1; + } + + uniform = mTexture[uniform]; + + if (uniform > -1) + { + gGL.getTexUnit(uniform)->bindFast(texture); + gGL.getTexUnit(uniform)->setTextureColorSpace(colorspace); + } + + return uniform; +} + +S32 LLGLSLShader::bindTexture(S32 uniform, LLRenderTarget* texture, bool depth, LLTexUnit::eTextureFilterOptions mode, U32 index) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + if (uniform < 0 || uniform >= (S32)mTexture.size()) + { + return -1; + } + + uniform = getTextureChannel(uniform); + + if (uniform > -1) + { + if (depth) { + gGL.getTexUnit(uniform)->bind(texture, true); + } + else { + bool has_mips = mode == LLTexUnit::TFO_TRILINEAR || mode == LLTexUnit::TFO_ANISOTROPIC; + gGL.getTexUnit(uniform)->bindManual(texture->getUsage(), texture->getTexture(index), has_mips); + } + + gGL.getTexUnit(uniform)->setTextureFilteringOption(mode); + } + + return uniform; +} + +S32 LLGLSLShader::bindTexture(const std::string& uniform, LLRenderTarget* texture, bool depth, LLTexUnit::eTextureFilterOptions mode) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + S32 channel = 0; + channel = getUniformLocation(uniform); + + return bindTexture(channel, texture, depth, mode); +} + +S32 LLGLSLShader::unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + S32 channel = 0; + channel = getUniformLocation(uniform); + + return unbindTexture(channel); +} + +S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + if (uniform < 0 || uniform >= (S32)mTexture.size()) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; + return -1; + } + + uniform = mTexture[uniform]; + + if (uniform > -1) + { + gGL.getTexUnit(uniform)->unbindFast(mode); + } + + return uniform; +} + +S32 LLGLSLShader::getTextureChannel(S32 uniform) const +{ + return mTexture[uniform]; +} + +S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + if (uniform < 0 || uniform >= (S32)mTexture.size()) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; + return -1; + } + S32 index = mTexture[uniform]; + if (index != -1) + { + gGL.getTexUnit(index)->activate(); + gGL.getTexUnit(index)->enable(mode); + gGL.getTexUnit(index)->setTextureColorSpace(space); + } + return index; +} + +S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + if (uniform < 0 || uniform >= (S32)mTexture.size()) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; + return -1; + } + S32 index = mTexture[uniform]; + if (index != -1 && gGL.getTexUnit(index)->getCurrType() != LLTexUnit::TT_NONE) + { + if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode && gGL.getTexUnit(index)->getCurrColorSpace() != space) + { + if (gDebugSession) + { + gFailLog << "Texture channel " << index << " texture type corrupted." << std::endl; + ll_fail("LLGLSLShader::disableTexture failed"); + } + else + { + LL_ERRS() << "Texture channel " << index << " texture type corrupted." << LL_ENDL; + } + } + gGL.getTexUnit(index)->disable(); + } + return index; +} + +void LLGLSLShader::uniform1i(U32 index, GLint x) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + llassert(sCurBoundShaderPtr == this); + if (mProgramObject) + { + if (mUniform.size() <= index) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + const auto& iter = mValue.find(mUniform[index]); + if (iter == mValue.end() || iter->second.mV[0] != x) + { + glUniform1i(mUniform[index], x); + mValue[mUniform[index]] = LLVector4(x, 0.f, 0.f, 0.f); + } + } + } +} + +void LLGLSLShader::uniform1f(U32 index, GLfloat x) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + llassert(sCurBoundShaderPtr == this); + + if (mProgramObject) + { + if (mUniform.size() <= index) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + const auto& iter = mValue.find(mUniform[index]); + if (iter == mValue.end() || iter->second.mV[0] != x) + { + glUniform1f(mUniform[index], x); + mValue[mUniform[index]] = LLVector4(x, 0.f, 0.f, 0.f); + } + } + } +} + +void LLGLSLShader::fastUniform1f(U32 index, GLfloat x) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + llassert(sCurBoundShaderPtr == this); + llassert(mProgramObject); + llassert(mUniform.size() <= index); + llassert(mUniform[index] >= 0); + glUniform1f(mUniform[index], x); +} + +void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + llassert(sCurBoundShaderPtr == this); + + if (mProgramObject) + { + if (mUniform.size() <= index) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + const auto& iter = mValue.find(mUniform[index]); + LLVector4 vec(x, y, 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec)) + { + glUniform2f(mUniform[index], x, y); + mValue[mUniform[index]] = vec; + } + } + } +} + +void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + llassert(sCurBoundShaderPtr == this); + + if (mProgramObject) + { + if (mUniform.size() <= index) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + const auto& iter = mValue.find(mUniform[index]); + LLVector4 vec(x, y, z, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec)) + { + glUniform3f(mUniform[index], x, y, z); + mValue[mUniform[index]] = vec; + } + } + } +} + +void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + llassert(sCurBoundShaderPtr == this); + + if (mProgramObject) + { + if (mUniform.size() <= index) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + const auto& iter = mValue.find(mUniform[index]); + LLVector4 vec(x, y, z, w); + if (iter == mValue.end() || shouldChange(iter->second, vec)) + { + glUniform4f(mUniform[index], x, y, z, w); + mValue[mUniform[index]] = vec; + } + } + } +} + +void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + llassert(sCurBoundShaderPtr == this); + + if (mProgramObject) + { + if (mUniform.size() <= index) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + const auto& iter = mValue.find(mUniform[index]); + LLVector4 vec(v[0], 0.f, 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) + { + glUniform1iv(mUniform[index], count, v); + mValue[mUniform[index]] = vec; + } + } + } +} + +void LLGLSLShader::uniform4iv(U32 index, U32 count, const GLint* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + llassert(sCurBoundShaderPtr == this); + + if (mProgramObject) + { + if (mUniform.size() <= index) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + const auto& iter = mValue.find(mUniform[index]); + LLVector4 vec(v[0], v[1], v[2], v[3]); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) + { + glUniform1iv(mUniform[index], count, v); + mValue[mUniform[index]] = vec; + } + } + } +} + + +void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + llassert(sCurBoundShaderPtr == this); + + if (mProgramObject) + { + if (mUniform.size() <= index) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + const auto& iter = mValue.find(mUniform[index]); + LLVector4 vec(v[0], 0.f, 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) + { + glUniform1fv(mUniform[index], count, v); + mValue[mUniform[index]] = vec; + } + } + } +} + +void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + llassert(sCurBoundShaderPtr == this); + + if (mProgramObject) + { + if (mUniform.size() <= index) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + const auto& iter = mValue.find(mUniform[index]); + LLVector4 vec(v[0], v[1], 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) + { + glUniform2fv(mUniform[index], count, v); + mValue[mUniform[index]] = vec; + } + } + } +} + +void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + llassert(sCurBoundShaderPtr == this); + + if (mProgramObject) + { + if (mUniform.size() <= index) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + const auto& iter = mValue.find(mUniform[index]); + LLVector4 vec(v[0], v[1], v[2], 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) + { + glUniform3fv(mUniform[index], count, v); + mValue[mUniform[index]] = vec; + } + } + } +} + +void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + llassert(sCurBoundShaderPtr == this); + + if (mProgramObject) + { + if (mUniform.size() <= index) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + const auto& iter = mValue.find(mUniform[index]); + LLVector4 vec(v[0], v[1], v[2], v[3]); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + glUniform4fv(mUniform[index], count, v); + mValue[mUniform[index]] = vec; + } + } + } +} + +void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + llassert(sCurBoundShaderPtr == this); + + if (mProgramObject) + { + if (mUniform.size() <= index) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + glUniformMatrix2fv(mUniform[index], count, transpose, v); + } + } +} + +void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + llassert(sCurBoundShaderPtr == this); + + if (mProgramObject) + { + if (mUniform.size() <= index) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + glUniformMatrix3fv(mUniform[index], count, transpose, v); + } + } +} + +void LLGLSLShader::uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + llassert(sCurBoundShaderPtr == this); + + if (mProgramObject) + { + if (mUniform.size() <= index) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + glUniformMatrix3x4fv(mUniform[index], count, transpose, v); + } + } +} + +void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + llassert(sCurBoundShaderPtr == this); + + if (mProgramObject) + { + if (mUniform.size() <= index) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + glUniformMatrix4fv(mUniform[index], count, transpose, v); + } + } +} + +GLint LLGLSLShader::getUniformLocation(const LLStaticHashedString& uniform) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + GLint ret = -1; + if (mProgramObject) + { + LLStaticStringTable::iterator iter = mUniformMap.find(uniform); + if (iter != mUniformMap.end()) + { + if (gDebugGL) + { + stop_glerror(); + if (iter->second != glGetUniformLocation(mProgramObject, uniform.String().c_str())) + { + LL_ERRS() << "Uniform does not match." << LL_ENDL; + } + stop_glerror(); + } + ret = iter->second; + } + } + + return ret; +} + +GLint LLGLSLShader::getUniformLocation(U32 index) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + GLint ret = -1; + if (mProgramObject) + { + if (index >= mUniform.size()) + { + LL_WARNS_ONCE("Shader") << "Uniform index " << index << " out of bounds " << (S32)mUniform.size() << LL_ENDL; + return ret; + } + return mUniform[index]; + } + + return ret; +} + +GLint LLGLSLShader::getAttribLocation(U32 attrib) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + + if (attrib < mAttribute.size()) + { + return mAttribute[attrib]; + } + else + { + return -1; + } +} + +void LLGLSLShader::uniform1i(const LLStaticHashedString& uniform, GLint v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + const auto& iter = mValue.find(location); + LLVector4 vec(v, 0.f, 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec)) + { + glUniform1i(location, v); + mValue[location] = vec; + } + } +} + +void LLGLSLShader::uniform1iv(const LLStaticHashedString& uniform, U32 count, const GLint* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + LLVector4 vec(v[0], 0, 0, 0); + const auto& iter = mValue.find(location); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + glUniform1iv(location, count, v); + mValue[location] = vec; + } + } +} + +void LLGLSLShader::uniform4iv(const LLStaticHashedString& uniform, U32 count, const GLint* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + LLVector4 vec(v[0], v[1], v[2], v[3]); + const auto& iter = mValue.find(location); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + glUniform4iv(location, count, v); + mValue[location] = vec; + } + } +} + +void LLGLSLShader::uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + const auto& iter = mValue.find(location); + LLVector4 vec(i, j, 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec)) + { + glUniform2i(location, i, j); + mValue[location] = vec; + } + } +} + + +void LLGLSLShader::uniform1f(const LLStaticHashedString& uniform, GLfloat v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + const auto& iter = mValue.find(location); + LLVector4 vec(v, 0.f, 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec)) + { + glUniform1f(location, v); + mValue[location] = vec; + } + } +} + +void LLGLSLShader::uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + const auto& iter = mValue.find(location); + LLVector4 vec(x, y, 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec)) + { + glUniform2f(location, x, y); + mValue[location] = vec; + } + } + +} + +void LLGLSLShader::uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + const auto& iter = mValue.find(location); + LLVector4 vec(x, y, z, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec)) + { + glUniform3f(location, x, y, z); + mValue[location] = vec; + } + } +} + +void LLGLSLShader::uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + const auto& iter = mValue.find(location); + LLVector4 vec(v[0], 0.f, 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) + { + glUniform1fv(location, count, v); + mValue[location] = vec; + } + } +} + +void LLGLSLShader::uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + const auto& iter = mValue.find(location); + LLVector4 vec(v[0], v[1], 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) + { + glUniform2fv(location, count, v); + mValue[location] = vec; + } + } +} + +void LLGLSLShader::uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + const auto& iter = mValue.find(location); + LLVector4 vec(v[0], v[1], v[2], 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) + { + glUniform3fv(location, count, v); + mValue[location] = vec; + } + } +} + +void LLGLSLShader::uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + LLVector4 vec(v); + const auto& iter = mValue.find(location); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + glUniform4fv(location, count, v); + mValue[location] = vec; + } + } +} + +void LLGLSLShader::uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + stop_glerror(); + glUniformMatrix4fv(location, count, transpose, v); + stop_glerror(); + } +} + + +void LLGLSLShader::vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + if (mAttribute[index] > 0) + { + glVertexAttrib4f(mAttribute[index], x, y, z, w); + } +} + +void LLGLSLShader::vertexAttrib4fv(U32 index, GLfloat* v) +{ + if (mAttribute[index] > 0) + { + glVertexAttrib4fv(mAttribute[index], v); + } +} + +void LLGLSLShader::setMinimumAlpha(F32 minimum) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + gGL.flush(); + uniform1f(LLShaderMgr::MINIMUM_ALPHA, minimum); +} + +void LLShaderUniforms::apply(LLGLSLShader* shader) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + for (auto& uniform : mIntegers) + { + shader->uniform1i(uniform.mUniform, uniform.mValue); + } + + for (auto& uniform : mFloats) + { + shader->uniform1f(uniform.mUniform, uniform.mValue); + } + + for (auto& uniform : mVectors) + { + shader->uniform4fv(uniform.mUniform, 1, uniform.mValue.mV); + } + + for (auto& uniform : mVector3s) + { + shader->uniform3fv(uniform.mUniform, 1, uniform.mValue.mV); + } +} + +LLUUID LLGLSLShader::hash() +{ + HBXXH128 hash_obj; + hash_obj.update(mName); + hash_obj.update(&mShaderGroup, sizeof(mShaderGroup)); + hash_obj.update(&mShaderLevel, sizeof(mShaderLevel)); + for (const auto& shdr_pair : mShaderFiles) + { + hash_obj.update(shdr_pair.first); + hash_obj.update(&shdr_pair.second, sizeof(GLenum)); + } + for (const auto& define_pair : mDefines) + { + hash_obj.update(define_pair.first); + hash_obj.update(define_pair.second); + + } + for (const auto& define_pair : LLGLSLShader::sGlobalDefines) + { + hash_obj.update(define_pair.first); + hash_obj.update(define_pair.second); + + } + hash_obj.update(&mFeatures, sizeof(LLShaderFeatures)); + hash_obj.update(gGLManager.mGLVendor); + hash_obj.update(gGLManager.mGLRenderer); + hash_obj.update(gGLManager.mGLVersionString); + return hash_obj.digest(); +} + +#ifdef LL_PROFILER_ENABLE_RENDER_DOC +void LLGLSLShader::setLabel(const char* label) { + LL_LABEL_OBJECT_GL(GL_PROGRAM, mProgramObject, strlen(label), label); +} +#endif -- cgit v1.2.3 From 2f4120038429c6aff865f153f708ceefb60d67f4 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 28 May 2024 09:45:40 -0500 Subject: Remove tinygltf dependency from LL::GLTF (#1541) * #1535 Image loading/saving support in boost::json driven GLTF parser * #1536 GLB Support in boost::json drvien GLTF parser --- indra/llrender/llglslshader.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra/llrender/llglslshader.cpp') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index f6b1ca3741..ecd0c6908b 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -1049,6 +1049,12 @@ void LLGLSLShader::bind() } } +void LLGLSLShader::bind(LLGLSLShader::GLTFVariant variant) +{ + llassert(mGLTFVariants.size() == LLGLSLShader::NUM_GLTF_VARIANTS); + mGLTFVariants[variant].bind(); +} + void LLGLSLShader::bind(bool rigged) { if (rigged) -- cgit v1.2.3 From 15fd13f83036ff781160957a21bb2d59771044bc Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 29 May 2024 16:56:39 -0500 Subject: #1530 Increase joint limit for GLTF Assets (#1582) * Migrate GLTF scene rendering to its own shaders * Add support for ambient occlusion map separate from metallic roughness map (or absent) * Use UBO's for GLTF joints * Better error handling of downloading GLTF assets --- indra/llrender/llglslshader.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'indra/llrender/llglslshader.cpp') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index ecd0c6908b..8ea134393a 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -983,17 +983,25 @@ bool LLGLSLShader::mapUniforms(const vector* uniforms) } //........................................................................................................................................ - if (mFeatures.hasReflectionProbes) // Set up block binding, in a way supported by Apple (rather than binding = 1 in .glsl). - { // See slide 35 and more of https://docs.huihoo.com/apple/wwdc/2011/session_420__advances_in_opengl_for_mac_os_x_lion.pdf - static const GLuint BLOCKBINDING = 1; //picked by us - //Get the index, similar to a uniform location - GLuint UBOBlockIndex = glGetUniformBlockIndex(mProgramObject, "ReflectionProbes"); + // Set up block binding, in a way supported by Apple (rather than binding = 1 in .glsl). + // See slide 35 and more of https://docs.huihoo.com/apple/wwdc/2011/session_420__advances_in_opengl_for_mac_os_x_lion.pdf + const char* ubo_names[] = + { + "ReflectionProbes", // UB_REFLECTION_PROBES + "GLTFJoints", // UB_GLTF_JOINTS + }; + + llassert(LL_ARRAY_SIZE(ubo_names) == NUM_UNIFORM_BLOCKS); + + for (U32 i = 0; i < NUM_UNIFORM_BLOCKS; ++i) + { + GLuint UBOBlockIndex = glGetUniformBlockIndex(mProgramObject, ubo_names[i]); if (UBOBlockIndex != GL_INVALID_INDEX) { - //Set this index to a binding index - glUniformBlockBinding(mProgramObject, UBOBlockIndex, BLOCKBINDING); + glUniformBlockBinding(mProgramObject, UBOBlockIndex, i); } } + unbind(); LL_DEBUGS("ShaderUniform") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL; @@ -1049,9 +1057,10 @@ void LLGLSLShader::bind() } } -void LLGLSLShader::bind(LLGLSLShader::GLTFVariant variant) +void LLGLSLShader::bind(U32 variant) { llassert(mGLTFVariants.size() == LLGLSLShader::NUM_GLTF_VARIANTS); + llassert(variant < LLGLSLShader::NUM_GLTF_VARIANTS); mGLTFVariants[variant].bind(); } -- cgit v1.2.3 From b42f9d836b4c0f7fbd4bdae1734021e2a09fdbe8 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sat, 1 Jun 2024 15:49:26 +0200 Subject: Re-enable a lot of compiler warnings for MSVC and address the C4267 "possible loss of precision" warnings --- indra/llrender/llglslshader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llrender/llglslshader.cpp') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 1651835b59..2caeb1c431 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -621,7 +621,7 @@ bool LLGLSLShader::mapAttributes(const std::vector* attrib } mAttribute.clear(); - U32 numAttributes = (attributes == NULL) ? 0 : attributes->size(); + U32 numAttributes = (attributes == NULL) ? 0U : static_cast(attributes->size()); #if LL_RELEASE_WITH_DEBUG_INFO mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, { -1, NULL }); #else @@ -843,7 +843,7 @@ bool LLGLSLShader::mapUniforms(const vector* uniforms) mTexture.clear(); mValue.clear(); //initialize arrays - U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size(); + U32 numUniforms = (uniforms == NULL) ? 0U : static_cast(uniforms->size()); mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); -- cgit v1.2.3 From 227e9be06832515fd10eb496d4a2a4528d1ebd92 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 10 Jun 2024 10:43:38 -0500 Subject: #1654 generate normals and tangents according to gltf specification (#1662) * Disable unloading of objects in background. * Add unlit GLTF shader variant --- indra/llrender/llglslshader.cpp | 71 +++++++++++------------------------------ 1 file changed, 19 insertions(+), 52 deletions(-) (limited to 'indra/llrender/llglslshader.cpp') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 8ea134393a..6a60914b80 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -381,13 +381,10 @@ void LLGLSLShader::unloadInternal() stop_glerror(); } -bool LLGLSLShader::createShader(std::vector* attributes, - std::vector* uniforms, - U32 varying_count, - const char** varyings) +bool LLGLSLShader::createShader() { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - + unloadInternal(); sInstances.insert(this); @@ -454,11 +451,11 @@ bool LLGLSLShader::createShader(std::vector* attributes, // Map attributes and uniforms if (success) { - success = mapAttributes(attributes); + success = mapAttributes(); } if (success) { - success = mapUniforms(uniforms); + success = mapUniforms(); } if (!success) { @@ -469,7 +466,7 @@ bool LLGLSLShader::createShader(std::vector* attributes, { LL_SHADER_LOADING_WARNS() << "Failed to link using shader level " << mShaderLevel << " trying again using shader level " << (mShaderLevel - 1) << LL_ENDL; mShaderLevel--; - return createShader(attributes, uniforms); + return createShader(); } else { @@ -602,7 +599,7 @@ void LLGLSLShader::attachObjects(GLuint* objects, S32 count) } } -bool LLGLSLShader::mapAttributes(const std::vector* attributes) +bool LLGLSLShader::mapAttributes() { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; @@ -621,11 +618,10 @@ bool LLGLSLShader::mapAttributes(const std::vector* attrib } mAttribute.clear(); - U32 numAttributes = (attributes == NULL) ? 0 : attributes->size(); #if LL_RELEASE_WITH_DEBUG_INFO - mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, { -1, NULL }); + mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size(), { -1, NULL }); #else - mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, -1); + mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size(), -1); #endif if (res) @@ -649,19 +645,6 @@ bool LLGLSLShader::mapAttributes(const std::vector* attrib LL_DEBUGS("ShaderUniform") << "Attribute " << name << " assigned to channel " << index << LL_ENDL; } } - if (attributes != NULL) - { - for (U32 i = 0; i < numAttributes; i++) - { - const char* name = (*attributes)[i].String().c_str(); - S32 index = glGetAttribLocation(mProgramObject, name); - if (index != -1) - { - mAttribute[LLShaderMgr::instance()->mReservedAttribs.size() + i] = index; - LL_DEBUGS("ShaderUniform") << "Attribute " << name << " assigned to channel " << index << LL_ENDL; - } - } - } return true; } @@ -669,7 +652,7 @@ bool LLGLSLShader::mapAttributes(const std::vector* attrib return false; } -void LLGLSLShader::mapUniform(GLint index, const vector* uniforms) +void LLGLSLShader::mapUniform(GLint index) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; @@ -756,21 +739,6 @@ void LLGLSLShader::mapUniform(GLint index, const vector* u return; } } - - if (uniforms != NULL) - { - for (U32 i = 0; i < uniforms->size(); i++) - { - if ((mUniform[i + LLShaderMgr::instance()->mReservedUniforms.size()] == -1) - && ((*uniforms)[i].String() == name)) - { - //found it - mUniform[i + LLShaderMgr::instance()->mReservedUniforms.size()] = location; - mTexture[i + LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type, size); - return; - } - } - } } } @@ -830,7 +798,7 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type, GLint return -1; } -bool LLGLSLShader::mapUniforms(const vector* uniforms) +bool LLGLSLShader::mapUniforms() { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; @@ -843,9 +811,8 @@ bool LLGLSLShader::mapUniforms(const vector* uniforms) mTexture.clear(); mValue.clear(); //initialize arrays - U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size(); - mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); - mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); + mUniform.resize(LLShaderMgr::instance()->mReservedUniforms.size(), -1); + mTexture.resize(LLShaderMgr::instance()->mReservedUniforms.size(), -1); bind(); @@ -946,26 +913,26 @@ bool LLGLSLShader::mapUniforms(const vector* uniforms) if (specularDiff || bumpLessDiff || envLessDiff || refLessDiff) { - mapUniform(diffuseMap, uniforms); + mapUniform(diffuseMap); skip_index.insert(diffuseMap); if (-1 != specularMap) { - mapUniform(specularMap, uniforms); + mapUniform(specularMap); skip_index.insert(specularMap); } if (-1 != bumpMap) { - mapUniform(bumpMap, uniforms); + mapUniform(bumpMap); skip_index.insert(bumpMap); } if (-1 != environmentMap) { - mapUniform(environmentMap, uniforms); + mapUniform(environmentMap); skip_index.insert(environmentMap); } if (-1 != reflectionMap) { - mapUniform(reflectionMap, uniforms); + mapUniform(reflectionMap); skip_index.insert(reflectionMap); } } @@ -979,7 +946,7 @@ bool LLGLSLShader::mapUniforms(const vector* uniforms) if (skip_index.end() != skip_index.find(i)) continue; //........................................................................................ - mapUniform(i, uniforms); + mapUniform(i); } //........................................................................................................................................ @@ -1057,7 +1024,7 @@ void LLGLSLShader::bind() } } -void LLGLSLShader::bind(U32 variant) +void LLGLSLShader::bind(U8 variant) { llassert(mGLTFVariants.size() == LLGLSLShader::NUM_GLTF_VARIANTS); llassert(variant < LLGLSLShader::NUM_GLTF_VARIANTS); -- cgit v1.2.3 From 148786999dc1fb5cd409373cfedae485420a69d9 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 11 Jun 2024 18:35:24 +0300 Subject: viewer#1698 Uniform being out of range shouldn't crash viewer --- indra/llrender/llglslshader.cpp | 59 ++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 19 deletions(-) (limited to 'indra/llrender/llglslshader.cpp') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 3697b4ca91..f5c698e20e 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -1094,7 +1094,8 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextu if (uniform < 0 || uniform >= (S32)mTexture.size()) { - LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << uniform << LL_ENDL; + llassert(false); return -1; } @@ -1115,6 +1116,8 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLRenderTarget* texture, bool depth, if (uniform < 0 || uniform >= (S32)mTexture.size()) { + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << uniform << LL_ENDL; + llassert(false); return -1; } @@ -1162,7 +1165,8 @@ S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode) if (uniform < 0 || uniform >= (S32)mTexture.size()) { - LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << uniform << LL_ENDL; + llassert(false); return -1; } @@ -1187,7 +1191,8 @@ S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTex if (uniform < 0 || uniform >= (S32)mTexture.size()) { - LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << uniform << LL_ENDL; + llassert(false); return -1; } @@ -1208,7 +1213,8 @@ S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTe if (uniform < 0 || uniform >= (S32)mTexture.size()) { - LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << uniform << LL_ENDL; + llassert(false); return -1; } S32 index = mTexture[uniform]; @@ -1239,7 +1245,8 @@ void LLGLSLShader::uniform1i(U32 index, GLint x) { if (mUniform.size() <= index) { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << index << LL_ENDL; + llassert(false); return; } @@ -1264,7 +1271,8 @@ void LLGLSLShader::uniform1f(U32 index, GLfloat x) { if (mUniform.size() <= index) { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << index << LL_ENDL; + llassert(false); return; } @@ -1299,7 +1307,8 @@ void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y) { if (mUniform.size() <= index) { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << index << LL_ENDL; + llassert(false); return; } @@ -1325,7 +1334,8 @@ void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z) { if (mUniform.size() <= index) { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << index << LL_ENDL; + llassert(false); return; } @@ -1351,7 +1361,8 @@ void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat { if (mUniform.size() <= index) { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << index << LL_ENDL; + llassert(false); return; } @@ -1377,7 +1388,8 @@ void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v) { if (mUniform.size() <= index) { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << index << LL_ENDL; + llassert(false); return; } @@ -1403,7 +1415,8 @@ void LLGLSLShader::uniform4iv(U32 index, U32 count, const GLint* v) { if (mUniform.size() <= index) { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << index << LL_ENDL; + llassert(false); return; } @@ -1430,7 +1443,8 @@ void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v) { if (mUniform.size() <= index) { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << index << LL_ENDL; + llassert(false); return; } @@ -1456,7 +1470,8 @@ void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v) { if (mUniform.size() <= index) { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << index << LL_ENDL; + llassert(false); return; } @@ -1482,7 +1497,8 @@ void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v) { if (mUniform.size() <= index) { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << index << LL_ENDL; + llassert(false); return; } @@ -1508,7 +1524,8 @@ void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v) { if (mUniform.size() <= index) { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << index << LL_ENDL; + llassert(false); return; } @@ -1535,7 +1552,8 @@ void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, c { if (mUniform.size() <= index) { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << index << LL_ENDL; + llassert(false); return; } @@ -1555,7 +1573,8 @@ void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, c { if (mUniform.size() <= index) { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << index << LL_ENDL; + llassert(false); return; } @@ -1575,7 +1594,8 @@ void LLGLSLShader::uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, { if (mUniform.size() <= index) { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << index << LL_ENDL; + llassert(false); return; } @@ -1595,7 +1615,8 @@ void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, c { if (mUniform.size() <= index) { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << index << LL_ENDL; + llassert(false); return; } -- cgit v1.2.3 From 15b3c9f1643368fe0c5356ea11288525bbe9fbb3 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Thu, 13 Jun 2024 02:22:03 +0200 Subject: Fix a few merge issues --- indra/llrender/llglslshader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llrender/llglslshader.cpp') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index e47c842228..45abb695cb 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -279,7 +279,7 @@ bool LLGLSLShader::readProfileQuery(bool for_runtime, bool force_read) GLuint64 samples_passed = 0; glGetQueryObjectui64v(mSamplesQuery, GL_QUERY_RESULT, &samples_passed); - U64 primitives_generated = 0; + GLuint64 primitives_generated = 0; glGetQueryObjectui64v(mPrimitivesQuery, GL_QUERY_RESULT, &primitives_generated); sTotalTimeElapsed += time_elapsed; -- cgit v1.2.3 From 375555012f92c1b836f2d122754f9facd050be62 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 14 Jun 2024 17:06:07 -0500 Subject: 1736 audit texture image unit usage on os x (#1739) * #1736 Remove some unused samplers from glsl files and refactor shader manager to assume 16 texture image units and 4 indexed texture units all the time. --- indra/llrender/llglslshader.cpp | 47 ++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 12 deletions(-) (limited to 'indra/llrender/llglslshader.cpp') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 45abb695cb..79979657f1 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -476,6 +476,7 @@ bool LLGLSLShader::createShader() } else if (mFeatures.mIndexedTextureChannels > 0) { //override texture channels for indexed texture rendering + llassert(mFeatures.mIndexedTextureChannels == LLGLSLShader::sIndexedTextureChannels); // these numbers must always match bind(); S32 channel_count = mFeatures.mIndexedTextureChannels; @@ -485,19 +486,41 @@ bool LLGLSLShader::createShader() uniform1i(uniName, i); } - S32 cur_tex = channel_count; //adjust any texture channels that might have been overwritten + //adjust any texture channels that might have been overwritten for (U32 i = 0; i < mTexture.size(); i++) { - if (mTexture[i] > -1 && mTexture[i] < channel_count) + if (mTexture[i] > -1) { - llassert(cur_tex < gGLManager.mNumTextureImageUnits); - uniform1i(i, cur_tex); - mTexture[i] = cur_tex++; + S32 new_tex = mTexture[i] + channel_count; + uniform1i(i, new_tex); + mTexture[i] = new_tex; } } + + // get the true number of active texture channels + mActiveTextureChannels = channel_count; + for (auto& tex : mTexture) + { + mActiveTextureChannels = llmax(mActiveTextureChannels, tex + 1); + } + + // when indexed texture channels are used, enforce an upper limit of 16 + // this should act as a canary in the coal mine for adding textures + // and breaking machines that are limited to 16 texture channels + llassert(mActiveTextureChannels <= 16); unbind(); } + LL_DEBUGS("GLSLTextureChannels") << mName << " has " << mActiveTextureChannels << " active texture channels" << LL_ENDL; + + for (U32 i = 0; i < mTexture.size(); i++) + { + if (mTexture[i] > -1) + { + LL_DEBUGS("GLSLTextureChannels") << "Texture " << LLShaderMgr::instance()->mReservedUniforms[i] << " assigned to channel " << mTexture[i] << LL_ENDL; + } + } + #ifdef LL_PROFILER_ENABLE_RENDER_DOC setLabel(mName.c_str()); #endif @@ -736,6 +759,10 @@ void LLGLSLShader::mapUniform(GLint index) //found it mUniform[i] = location; mTexture[i] = mapUniformTextureChannel(location, type, size); + if (mTexture[i] != -1) + { + LL_DEBUGS("GLSLTextureChannels") << name << " assigned to texture channel " << mTexture[i] << LL_ENDL; + } return; } } @@ -774,25 +801,21 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type, GLint if (size == 1) { glUniform1i(location, mActiveTextureChannels); - LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL; mActiveTextureChannels++; } else { //is array of textures, make sequential after this texture - GLint channel[32]; // <=== only support up to 32 texture channels - llassert(size <= 32); - size = llmin(size, 32); + GLint channel[16]; // <=== only support up to 16 texture channels + llassert(size <= 16); + size = llmin(size, 16); for (int i = 0; i < size; ++i) { channel[i] = mActiveTextureChannels++; } glUniform1iv(location, size, channel); - LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << - (mActiveTextureChannels - size) << " through " << (mActiveTextureChannels - 1) << LL_ENDL; } - llassert(mActiveTextureChannels <= 32); // too many textures (probably) return ret; } return -1; -- cgit v1.2.3 From 80ea30af1a8b38360f71c29cc45872c4399dab0d Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 21 Jun 2024 13:13:08 -0500 Subject: #1769 gltf optimization pass (#1816) #1814 and #1517 Fix mirror update rate and occlusion culling --- indra/llrender/llglslshader.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra/llrender/llglslshader.cpp') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index e22df46b28..25e4a88f28 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -54,6 +54,8 @@ using std::string; GLuint LLGLSLShader::sCurBoundShader = 0; LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL; S32 LLGLSLShader::sIndexedTextureChannels = 0; +U32 LLGLSLShader::sMaxGLTFMaterials = 0; +U32 LLGLSLShader::sMaxGLTFNodes = 0; bool LLGLSLShader::sProfileEnabled = false; std::set LLGLSLShader::sInstances; LLGLSLShader::defines_map_t LLGLSLShader::sGlobalDefines; @@ -978,7 +980,9 @@ bool LLGLSLShader::mapUniforms() const char* ubo_names[] = { "ReflectionProbes", // UB_REFLECTION_PROBES - "GLTFJoints", // UB_GLTF_JOINTS + "GLTFJoints", // UB_GLTF_JOINTS + "GLTFNodes", // UB_GLTF_NODES + "GLTFMaterials", // UB_GLTF_MATERIALS }; llassert(LL_ARRAY_SIZE(ubo_names) == NUM_UNIFORM_BLOCKS); -- cgit v1.2.3