summaryrefslogtreecommitdiff
path: root/indra/llrender
diff options
context:
space:
mode:
authorMerov Linden <merov@lindenlab.com>2013-06-19 12:24:44 -0700
committerMerov Linden <merov@lindenlab.com>2013-06-19 12:24:44 -0700
commitb3c010ea7130331d454c480b82d1309bac712004 (patch)
tree8f5e2ba709ebd52400f2831785e0c07c3396815f /indra/llrender
parentd65f09ebcafe6ca968236a9991961983d4cd7a47 (diff)
parent2655c7a17ae38a073dcf8f05b0127b68edc34c95 (diff)
Pull merge lindenlab/viewer-release
Diffstat (limited to 'indra/llrender')
-rwxr-xr-xindra/llrender/CMakeLists.txt2
-rwxr-xr-xindra/llrender/llgl.cpp42
-rwxr-xr-xindra/llrender/llgl.h8
-rwxr-xr-xindra/llrender/llglheaders.h16
-rwxr-xr-xindra/llrender/llglslshader.cpp305
-rwxr-xr-xindra/llrender/llglslshader.h41
-rw-r--r--indra/llrender/llimagegl.cpp50
-rwxr-xr-xindra/llrender/llrender.h8
-rwxr-xr-xindra/llrender/llshadermgr.cpp44
-rwxr-xr-xindra/llrender/llshadermgr.h10
-rwxr-xr-xindra/llrender/llvertexbuffer.cpp91
-rwxr-xr-xindra/llrender/llvertexbuffer.h8
12 files changed, 560 insertions, 65 deletions
diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt
index 669b70aa43..dba12d048e 100755
--- a/indra/llrender/CMakeLists.txt
+++ b/indra/llrender/CMakeLists.txt
@@ -92,7 +92,7 @@ if (BUILD_HEADLESS)
set_property(TARGET llrenderheadless
PROPERTY COMPILE_DEFINITIONS LL_MESA=1 LL_MESA_HEADLESS=1
- )
+ )
target_link_libraries(llrenderheadless
${LLCOMMON_LIBRARIES}
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 6c798aa4ed..088ba95b75 100755
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -86,7 +86,7 @@ void APIENTRY gl_debug_callback(GLenum source,
}
else
{
- llwarns << "----- GL WARNING -------" << llendl;
+ llwarns << "----- GL WARNING -------" << llendl;
}
llwarns << "Type: " << std::hex << type << llendl;
llwarns << "ID: " << std::hex << id << llendl;
@@ -216,6 +216,11 @@ PFNGLGETQUERYIVARBPROC glGetQueryivARB = NULL;
PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB = NULL;
PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB = NULL;
+// GL_ARB_timer_query
+PFNGLQUERYCOUNTERPROC glQueryCounter = NULL;
+PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v = NULL;
+PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v = NULL;
+
// GL_ARB_point_parameters
PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB = NULL;
PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB = NULL;
@@ -421,6 +426,7 @@ LLGLManager::LLGLManager() :
mHasFragmentShader(FALSE),
mNumTextureImageUnits(0),
mHasOcclusionQuery(FALSE),
+ mHasTimerQuery(FALSE),
mHasOcclusionQuery2(FALSE),
mHasPointParameters(FALSE),
mHasDrawBuffers(FALSE),
@@ -445,7 +451,9 @@ LLGLManager::LLGLManager() :
mIsGFFX(FALSE),
mATIOffsetVerticalLines(FALSE),
mATIOldDriver(FALSE),
-
+#if LL_DARWIN
+ mIsMobileGF(FALSE),
+#endif
mHasRequirements(TRUE),
mHasSeparateSpecularColor(FALSE),
@@ -637,6 +645,13 @@ bool LLGLManager::initGL()
{
mIsGF3 = TRUE;
}
+#if LL_DARWIN
+ else if ((mGLRenderer.find("9400M") != std::string::npos)
+ || (mGLRenderer.find("9600M") != std::string::npos))
+ {
+ mIsMobileGF = TRUE;
+ }
+#endif
}
else if (mGLVendor.find("INTEL") != std::string::npos
@@ -745,12 +760,13 @@ bool LLGLManager::initGL()
{ //using multisample textures on ATI results in black screen for some reason
mHasTextureMultisample = FALSE;
}
-#endif
+
if (mIsIntel && mGLVersion <= 3.f)
{ //never try to use framebuffer objects on older intel drivers (crashy)
mHasFramebufferObject = FALSE;
}
+#endif
if (mHasFramebufferObject)
{
@@ -947,13 +963,15 @@ void LLGLManager::initExtensions()
mHasARBEnvCombine = ExtensionExists("GL_ARB_texture_env_combine", gGLHExts.mSysExts);
mHasCompressedTextures = glh_init_extensions("GL_ARB_texture_compression");
mHasOcclusionQuery = ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts);
+ mHasTimerQuery = ExtensionExists("GL_ARB_timer_query", gGLHExts.mSysExts);
mHasOcclusionQuery2 = ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts);
mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts);
mHasVertexArrayObject = ExtensionExists("GL_ARB_vertex_array_object", gGLHExts.mSysExts);
mHasSync = ExtensionExists("GL_ARB_sync", gGLHExts.mSysExts);
mHasMapBufferRange = ExtensionExists("GL_ARB_map_buffer_range", gGLHExts.mSysExts);
mHasFlushBufferRange = ExtensionExists("GL_APPLE_flush_buffer_range", gGLHExts.mSysExts);
- mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts);
+ //mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts);
+ mHasDepthClamp = FALSE;
// mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad
#ifdef GL_ARB_framebuffer_object
mHasFramebufferObject = ExtensionExists("GL_ARB_framebuffer_object", gGLHExts.mSysExts);
@@ -963,6 +981,15 @@ void LLGLManager::initExtensions()
ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts) &&
ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts);
#endif
+#ifdef GL_EXT_texture_sRGB
+ mHassRGBTexture = ExtensionExists("GL_EXT_texture_sRGB", gGLHExts.mSysExts);
+#endif
+
+#ifdef GL_ARB_framebuffer_sRGB
+ mHassRGBFramebuffer = ExtensionExists("GL_ARB_framebuffer_sRGB", gGLHExts.mSysExts);
+#else
+ mHassRGBFramebuffer = ExtensionExists("GL_EXT_framebuffer_sRGB", gGLHExts.mSysExts);
+#endif
mHasMipMapGeneration = mHasFramebufferObject || mGLVersion >= 1.4f;
@@ -1253,6 +1280,13 @@ void LLGLManager::initExtensions()
glGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectivARB");
glGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectuivARB");
}
+ if (mHasTimerQuery)
+ {
+ llinfos << "initExtensions() TimerQuery-related procs..." << llendl;
+ glQueryCounter = (PFNGLQUERYCOUNTERPROC) GLH_EXT_GET_PROC_ADDRESS("glQueryCounter");
+ glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC) GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjecti64v");
+ glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC) GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectui64v");
+ }
if (mHasPointParameters)
{
llinfos << "initExtensions() PointParameters-related procs..." << llendl;
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index d70e764769..60597fd090 100755
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -98,6 +98,7 @@ public:
BOOL mHasFragmentShader;
S32 mNumTextureImageUnits;
BOOL mHasOcclusionQuery;
+ BOOL mHasTimerQuery;
BOOL mHasOcclusionQuery2;
BOOL mHasPointParameters;
BOOL mHasDrawBuffers;
@@ -115,6 +116,8 @@ public:
BOOL mHasARBEnvCombine;
BOOL mHasCubeMap;
BOOL mHasDebugOutput;
+ BOOL mHassRGBTexture;
+ BOOL mHassRGBFramebuffer;
// Vendor-specific extensions
BOOL mIsATI;
@@ -126,6 +129,11 @@ public:
BOOL mATIOffsetVerticalLines;
BOOL mATIOldDriver;
+#if LL_DARWIN
+ // Needed to distinguish problem cards on older Macs that break with Materials
+ BOOL mIsMobileGF;
+#endif
+
// Whether this version of GL is good enough for SL to use
BOOL mHasRequirements;
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index 509de51f4d..dace572953 100755
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -116,6 +116,11 @@ extern PFNGLGETQUERYIVARBPROC glGetQueryivARB;
extern PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB;
extern PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB;
+// GL_ARB_timer_query
+extern PFNGLQUERYCOUNTERPROC glQueryCounter;
+extern PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v;
+extern PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v;
+
// GL_ARB_point_parameters
extern PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB;
extern PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB;
@@ -378,6 +383,11 @@ extern PFNGLGETQUERYIVARBPROC glGetQueryivARB;
extern PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB;
extern PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB;
+// GL_ARB_timer_query
+extern PFNGLQUERYCOUNTERPROC glQueryCounter;
+extern PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v;
+extern PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v;
+
// GL_ARB_point_parameters
extern PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB;
extern PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB;
@@ -619,6 +629,12 @@ extern PFNGLGETQUERYIVARBPROC glGetQueryivARB;
extern PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB;
extern PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB;
+// GL_ARB_timer_query
+extern PFNGLQUERYCOUNTERPROC glQueryCounter;
+extern PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v;
+extern PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v;
+
+
// GL_ARB_point_parameters
extern PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB;
extern PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB;
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 7cbf39096e..62191b4c1a 100755
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -53,6 +53,12 @@ GLhandleARB LLGLSLShader::sCurBoundShader = 0;
LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL;
S32 LLGLSLShader::sIndexedTextureChannels = 0;
bool LLGLSLShader::sNoFixedFunction = false;
+bool LLGLSLShader::sProfileEnabled = false;
+std::set<LLGLSLShader*> LLGLSLShader::sInstances;
+U64 LLGLSLShader::sTotalTimeElapsed = 0;
+U32 LLGLSLShader::sTotalTrianglesDrawn = 0;
+U64 LLGLSLShader::sTotalSamplesDrawn = 0;
+U32 LLGLSLShader::sTotalDrawCalls = 0;
//UI shader -- declared here so llui_libtest will link properly
LLGLSLShader gUIProgram;
@@ -87,19 +93,194 @@ LLShaderFeatures::LLShaderFeatures()
//===============================
// LLGLSL Shader implementation
//===============================
+
+//static
+void LLGLSLShader::initProfile()
+{
+ sProfileEnabled = true;
+ sTotalTimeElapsed = 0;
+ sTotalTrianglesDrawn = 0;
+ sTotalSamplesDrawn = 0;
+ sTotalDrawCalls = 0;
+
+ for (std::set<LLGLSLShader*>::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()
+{
+ sProfileEnabled = false;
+
+ std::vector<LLGLSLShader*> sorted;
+
+ for (std::set<LLGLSLShader*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter)
+ {
+ sorted.push_back(*iter);
+ }
+
+ std::sort(sorted.begin(), sorted.end(), LLGLSLShaderCompareTimeElapsed());
+
+ for (std::vector<LLGLSLShader*>::iterator iter = sorted.begin(); iter != sorted.end(); ++iter)
+ {
+ (*iter)->dumpStats();
+ }
+
+ llinfos << "-----------------------------------" << llendl;
+ llinfos << "Total rendering time: " << llformat("%.4f ms", sTotalTimeElapsed/1000000.f) << llendl;
+ llinfos << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn/1000000.f) << llendl;
+ llinfos << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn/1000000.f) << llendl;
+}
+
+void LLGLSLShader::clearStats()
+{
+ mTrianglesDrawn = 0;
+ mTimeElapsed = 0;
+ mSamplesDrawn = 0;
+ mDrawCalls = 0;
+}
+
+void LLGLSLShader::dumpStats()
+{
+ if (mDrawCalls > 0)
+ {
+ llinfos << "=============================================" << llendl;
+ llinfos << mName << llendl;
+ for (U32 i = 0; i < mShaderFiles.size(); ++i)
+ {
+ llinfos << mShaderFiles[i].first << llendl;
+ }
+ llinfos << "=============================================" << llendl;
+
+ 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_calls = (F32) mDrawCalls/(F32)sTotalDrawCalls*100.f;
+ U32 avg_batch = mTrianglesDrawn/mDrawCalls;
+
+ llinfos << "Triangles Drawn: " << mTrianglesDrawn << " " << llformat("(%.2f pct of total, %.3f million/sec)", pct_tris, tris_sec ) << llendl;
+ llinfos << "Draw Calls: " << mDrawCalls << " " << llformat("(%.2f pct of total, avg %d tris/call)", pct_calls, avg_batch) << llendl;
+ llinfos << "SamplesDrawn: " << mSamplesDrawn << " " << llformat("(%.2f pct of total, %.3f billion/sec)", pct_samples, samples_sec) << llendl;
+ llinfos << "Time Elapsed: " << mTimeElapsed << " " << llformat("(%.2f pct of total, %.5f ms)\n", (F32) ((F64)mTimeElapsed/(F64)sTotalTimeElapsed)*100.f, ms) << llendl;
+ }
+}
+
+//static
+void LLGLSLShader::startProfile()
+{
+ if (sProfileEnabled && sCurBoundShaderPtr)
+ {
+ sCurBoundShaderPtr->placeProfileQuery();
+ }
+
+}
+
+//static
+void LLGLSLShader::stopProfile(U32 count, U32 mode)
+{
+ if (sProfileEnabled)
+ {
+ sCurBoundShaderPtr->readProfileQuery(count, mode);
+ }
+}
+
+void LLGLSLShader::placeProfileQuery()
+{
+#if !LL_DARWIN
+ if (mTimerQuery == 0)
+ {
+ glGenQueriesARB(1, &mTimerQuery);
+ }
+
+ glBeginQueryARB(GL_SAMPLES_PASSED, 1);
+ glBeginQueryARB(GL_TIME_ELAPSED, mTimerQuery);
+#endif
+}
+
+void LLGLSLShader::readProfileQuery(U32 count, U32 mode)
+{
+#if !LL_DARWIN
+ glEndQueryARB(GL_TIME_ELAPSED);
+ glEndQueryARB(GL_SAMPLES_PASSED);
+
+ U64 time_elapsed = 0;
+ glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT, &time_elapsed);
+
+ U64 samples_passed = 0;
+ glGetQueryObjectui64v(1, GL_QUERY_RESULT, &samples_passed);
+
+ sTotalTimeElapsed += time_elapsed;
+ mTimeElapsed += time_elapsed;
+
+ sTotalSamplesDrawn += samples_passed;
+ mSamplesDrawn += samples_passed;
+
+ U32 tri_count = 0;
+ switch (mode)
+ {
+ case LLRender::TRIANGLES: tri_count = count/3; break;
+ case LLRender::TRIANGLE_FAN: tri_count = count-2; break;
+ case LLRender::TRIANGLE_STRIP: tri_count = count-2; break;
+ default: tri_count = count; break; //points lines etc just use primitive count
+ }
+
+ mTrianglesDrawn += tri_count;
+ sTotalTrianglesDrawn += tri_count;
+
+ sTotalDrawCalls++;
+ mDrawCalls++;
+#endif
+}
+
+
+
LLGLSLShader::LLGLSLShader()
- : mProgramObject(0), mActiveTextureChannels(0), mShaderLevel(0), mShaderGroup(SG_DEFAULT), mUniformsDirty(FALSE)
+ : mProgramObject(0),
+ mAttributeMask(0),
+ mTotalUniformSize(0),
+ mActiveTextureChannels(0),
+ mShaderLevel(0),
+ mShaderGroup(SG_DEFAULT),
+ mUniformsDirty(FALSE),
+ mTimerQuery(0)
{
+
+}
+LLGLSLShader::~LLGLSLShader()
+{
+
}
void LLGLSLShader::unload()
{
+ sInstances.erase(this);
+
stop_glerror();
mAttribute.clear();
mTexture.clear();
mUniform.clear();
mShaderFiles.clear();
+ mDefines.clear();
if (mProgramObject)
{
@@ -133,6 +314,8 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
U32 varying_count,
const char** varyings)
{
+ sInstances.insert(this);
+
//reloading, reset matrix hash values
for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i)
{
@@ -150,7 +333,7 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin();
for ( ; fileIter != mShaderFiles.end(); fileIter++ )
{
- GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, mFeatures.mIndexedTextureChannels);
+ GLhandleARB 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 > 0)
{
@@ -285,6 +468,8 @@ BOOL LLGLSLShader::mapAttributes(const vector<string> * attributes)
if (res)
{ //read back channel locations
+ mAttributeMask = 0;
+
//read back reserved channels first
for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++)
{
@@ -293,6 +478,7 @@ BOOL LLGLSLShader::mapAttributes(const vector<string> * attributes)
if (index != -1)
{
mAttribute[i] = index;
+ mAttributeMask |= 1 << i;
LL_DEBUGS("ShaderLoading") << "Attribute " << name << " assigned to channel " << index << LL_ENDL;
}
}
@@ -325,11 +511,56 @@ void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms)
GLenum type;
GLsizei length;
- GLint size;
+ GLint size = -1;
char name[1024]; /* Flawfinder: ignore */
name[0] = 0;
+
glGetActiveUniformARB(mProgramObject, index, 1024, &length, &size, &type, (GLcharARB *)name);
+#if !LL_DARWIN
+ 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;
+ }
+#endif
+
S32 location = glGetUniformLocationARB(mProgramObject, name);
if (location != -1)
{
@@ -372,11 +603,21 @@ void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms)
}
}
}
- }
+}
+
+void LLGLSLShader::addPermutation(std::string name, std::string value)
+{
+ mDefines[name] = value;
+}
+
+void LLGLSLShader::removePermutation(std::string name)
+{
+ mDefines[name].erase();
+}
GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
{
- if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB ||
+ if ((type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB) ||
type == GL_SAMPLER_2D_MULTISAMPLE)
{ //this here is a texture
glUniform1iARB(location, mActiveTextureChannels);
@@ -390,6 +631,7 @@ BOOL LLGLSLShader::mapUniforms(const vector<string> * uniforms)
{
BOOL res = TRUE;
+ mTotalUniformSize = 0;
mActiveTextureChannels = 0;
mUniform.clear();
mUniformMap.clear();
@@ -413,6 +655,7 @@ BOOL LLGLSLShader::mapUniforms(const vector<string> * uniforms)
unbind();
+ LL_DEBUGS("ShaderLoading") << "Total Uniform Size: " << mTotalUniformSize << llendl;
return res;
}
@@ -471,6 +714,58 @@ void LLGLSLShader::bindNoShader(void)
}
}
+S32 LLGLSLShader::bindTexture(const std::string &uniform, LLTexture *texture, LLTexUnit::eTextureType mode)
+{
+ S32 channel = 0;
+ channel = getUniformLocation(uniform);
+
+ return bindTexture(channel, texture, mode);
+}
+
+S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode)
+{
+ if (uniform < 0 || uniform >= (S32)mTexture.size())
+ {
+ UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL;
+ return -1;
+ }
+
+ uniform = mTexture[uniform];
+
+ if (uniform > -1)
+ {
+ gGL.getTexUnit(uniform)->bind(texture, mode);
+ }
+
+ return uniform;
+}
+
+S32 LLGLSLShader::unbindTexture(const std::string &uniform, LLTexUnit::eTextureType mode)
+{
+ S32 channel = 0;
+ channel = getUniformLocation(uniform);
+
+ return unbindTexture(channel);
+}
+
+S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode)
+{
+ if (uniform < 0 || uniform >= (S32)mTexture.size())
+ {
+ UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL;
+ return -1;
+ }
+
+ uniform = mTexture[uniform];
+
+ if (uniform > -1)
+ {
+ gGL.getTexUnit(uniform)->unbind(mode);
+ }
+
+ return uniform;
+}
+
S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode)
{
if (uniform < 0 || uniform >= (S32)mTexture.size())
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index cf21101e35..3c775cde27 100755
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -67,14 +67,29 @@ public:
SG_WATER
};
+ static std::set<LLGLSLShader*> sInstances;
+ static bool sProfileEnabled;
+
LLGLSLShader();
+ ~LLGLSLShader();
static GLhandleARB sCurBoundShader;
static LLGLSLShader* sCurBoundShaderPtr;
static S32 sIndexedTextureChannels;
static bool sNoFixedFunction;
+ static void initProfile();
+ static void finishProfile();
+
+ static void startProfile();
+ static void stopProfile(U32 count, U32 mode);
+
void unload();
+ void clearStats();
+ void dumpStats();
+ void placeProfileQuery();
+ void readProfileQuery(U32 count, U32 mode);
+
BOOL createShader(std::vector<std::string> * attributes,
std::vector<std::string> * uniforms,
U32 varying_count = 0,
@@ -123,12 +138,22 @@ public:
GLint getAttribLocation(U32 attrib);
GLint mapUniformTextureChannel(GLint location, GLenum type);
+ void addPermutation(std::string name, std::string value);
+ void removePermutation(std::string name);
+
//enable/disable texture channel for specified uniform
//if given texture uniform is active in the shader,
//the corresponding channel will be active upon return
//returns channel texture is enabled in from [0-MAX)
S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
- S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+ S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+
+ // bindTexture returns the texture unit we've bound the texture to.
+ // You can reuse the return value to unbind a texture when required.
+ S32 bindTexture(const std::string& uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+ S32 bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+ S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+ S32 unbindTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
BOOL link(BOOL suppress_errors = FALSE);
void bind();
@@ -142,10 +167,12 @@ public:
GLhandleARB mProgramObject;
std::vector<GLint> mAttribute; //lookup table of attribute enum to attribute channel
+ U32 mAttributeMask; //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask())
std::vector<GLint> mUniform; //lookup table of uniform enum to uniform location
std::map<std::string, GLint> mUniformMap; //lookup map of uniform name to uniform location
std::map<GLint, LLVector4> mValue; //lookup map of uniform location to last known value
std::vector<GLint> mTexture;
+ S32 mTotalUniformSize;
S32 mActiveTextureChannels;
S32 mShaderLevel;
S32 mShaderGroup;
@@ -153,6 +180,18 @@ public:
LLShaderFeatures mFeatures;
std::vector< std::pair< std::string, GLenum > > mShaderFiles;
std::string mName;
+ boost::unordered_map<std::string, std::string> mDefines;
+
+ //statistcis for profiling shader performance
+ U32 mTimerQuery;
+ U64 mTimeElapsed;
+ static U64 sTotalTimeElapsed;
+ U32 mTrianglesDrawn;
+ static U32 sTotalTrianglesDrawn;
+ U64 mSamplesDrawn;
+ static U64 sTotalSamplesDrawn;
+ U32 mDrawCalls;
+ static U32 sTotalDrawCalls;
};
//UI shader (declared here so llui_libtest will link properly)
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 5c171d372c..38764eba23 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -748,12 +748,16 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
S32 height = getHeight(mCurrentDiscardLevel);
S32 nummips = mMaxDiscardLevel - mCurrentDiscardLevel + 1;
S32 w = width, h = height;
+
+
+ const U8* new_data = 0;
+ (void)new_data;
+
const U8* prev_mip_data = 0;
const U8* cur_mip_data = 0;
#ifdef SHOW_ASSERT
S32 cur_mip_size = 0;
#endif
-
mMipLevels = nummips;
for (int m=0; m<nummips; m++)
@@ -773,14 +777,22 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
llassert(cur_mip_size == bytes*4);
#endif
U8* new_data = new U8[bytes];
+
+#ifdef SHOW_ASSERT
+ llassert(prev_mip_data);
+ llassert(cur_mip_size == bytes*4);
llassert_always(new_data);
+#endif
+
LLImageBase::generateMip(prev_mip_data, new_data, w, h, mComponents);
cur_mip_data = new_data;
#ifdef SHOW_ASSERT
cur_mip_size = bytes;
#endif
+
}
llassert(w > 0 && h > 0 && cur_mip_data);
+ (void)cur_mip_data;
{
// LLFastTimer t1(FTM_TEMP4);
if(mFormatSwapBytes)
@@ -1119,30 +1131,30 @@ void LLImageGL::deleteTextures(LLTexUnit::eTextureType type, U32 format, S32 mip
default:
{
if (type == LLTexUnit::TT_CUBE_MAP || mip_levels == -1)
- { //unknown internal format or unknown number of mip levels, not safe to reuse
- glDeleteTextures(numTextures, textures);
- }
- else
- {
- for (S32 i = 0; i < numTextures; ++i)
- { //remove texture from VRAM by setting its size to zero
+ { //unknown internal format or unknown number of mip levels, not safe to reuse
+ glDeleteTextures(numTextures, textures);
+ }
+ else
+ {
+ for (S32 i = 0; i < numTextures; ++i)
+ { //remove texture from VRAM by setting its size to zero
- for (S32 j = 0; j <= mip_levels; j++)
- {
- gGL.getTexUnit(0)->bindManual(type, textures[i]);
+ for (S32 j = 0; j <= mip_levels; j++)
+ {
+ gGL.getTexUnit(0)->bindManual(type, textures[i]);
U32 internal_type = LLTexUnit::getInternalType(type);
glTexImage2D(internal_type, j, format, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
stop_glerror();
- }
+ }
- llassert(std::find(sDeadTextureList[type][format].begin(),
- sDeadTextureList[type][format].end(), textures[i]) ==
- sDeadTextureList[type][format].end());
+ llassert(std::find(sDeadTextureList[type][format].begin(),
+ sDeadTextureList[type][format].end(), textures[i]) ==
+ sDeadTextureList[type][format].end());
- sDeadTextureList[type][format].push_back(textures[i]);
- }
- }
- }
+ sDeadTextureList[type][format].push_back(textures[i]);
+ }
+ }
+ }
break;
}
}
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 78a310e525..98222939e7 100755
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -262,6 +262,14 @@ class LLRender
friend class LLTexUnit;
public:
+ enum eTexIndex
+ {
+ DIFFUSE_MAP = 0,
+ NORMAL_MAP,
+ SPECULAR_MAP,
+ NUM_TEXTURE_CHANNELS,
+ };
+
typedef enum {
TRIANGLES = 0,
TRIANGLE_STRIP,
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index b6a9a6b653..fea4ee2819 100755
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -521,7 +521,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns)
}
}
-GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels)
+GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, boost::unordered_map<std::string, std::string>* defines, S32 texture_index_channels)
{
GLenum error = GL_NO_ERROR;
if (gDebugGL)
@@ -650,13 +650,15 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
text[count++] = strdup("#define shadow2DRect(a,b) vec2(texture(a,b))\n");
}
}
-
- //copy preprocessor definitions into buffer
- for (std::map<std::string,std::string>::iterator iter = mDefinitions.begin(); iter != mDefinitions.end(); ++iter)
+
+ if (defines)
+ {
+ for (boost::unordered_map<std::string,std::string>::iterator iter = defines->begin(); iter != defines->end(); ++iter)
{
std::string define = "#define " + iter->first + " " + iter->second + "\n";
text[count++] = (GLcharARB *) strdup(define.c_str());
}
+ }
if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER_ARB)
{
@@ -693,6 +695,8 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
}
*/
+ text[count++] = strdup("#define HAS_DIFFUSE_LOOKUP 1\n");
+
//uniform declartion
for (S32 i = 0; i < texture_index_channels; ++i)
{
@@ -750,6 +754,10 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
llerrs << "Indexed texture rendering requires GLSL 1.30 or later." << llendl;
}
}
+ else
+ {
+ text[count++] = strdup("#define HAS_DIFFUSE_LOOKUP 0\n");
+ }
//copy file into memory
while( fgets((char *)buff, 1024, file) != NULL && count < LL_ARRAY_SIZE(text) )
@@ -806,7 +814,6 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
//an error occured, print log
LL_WARNS("ShaderLoading") << "GLSL Compilation Error: (" << error << ") in " << filename << LL_ENDL;
dumpObjectLog(ret);
-
#if LL_WINDOWS
std::stringstream ostr;
//dump shader source for debugging
@@ -824,8 +831,20 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
}
LL_WARNS("ShaderLoading") << "\n" << ostr.str() << llendl;
-#endif // LL_WINDOWS
-
+#else
+ std::string str;
+
+ for (GLuint i = 0; i < count; i++) {
+ str.append(text[i]);
+
+ if (i % 128 == 0)
+ {
+ LL_WARNS("ShaderLoading") << str << llendl;
+ str = "";
+ }
+ }
+#endif
+
ret = 0;
}
}
@@ -854,7 +873,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
if (shader_level > 1)
{
shader_level--;
- return loadShaderFile(filename,shader_level,type,texture_index_channels);
+ return loadShaderFile(filename,shader_level,type, defines, texture_index_channels);
}
LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL;
}
@@ -958,7 +977,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedAttribs.push_back("texcoord3");
mReservedAttribs.push_back("diffuse_color");
mReservedAttribs.push_back("emissive");
- mReservedAttribs.push_back("binormal");
+ mReservedAttribs.push_back("tangent");
mReservedAttribs.push_back("weight");
mReservedAttribs.push_back("weight4");
mReservedAttribs.push_back("clothing");
@@ -1055,6 +1074,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("minimum_alpha");
+ mReservedUniforms.push_back("emissive_brightness");
mReservedUniforms.push_back("shadow_matrix");
mReservedUniforms.push_back("env_mat");
@@ -1115,6 +1135,12 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("lightMap");
mReservedUniforms.push_back("bloomMap");
mReservedUniforms.push_back("projectionMap");
+
+ mReservedUniforms.push_back("global_gamma");
+ mReservedUniforms.push_back("texture_gamma");
+
+ mReservedUniforms.push_back("specular_color");
+ mReservedUniforms.push_back("env_intensity");
llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS);
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index 7a16b7c20f..c049e935b8 100755
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -109,6 +109,7 @@ public:
GLOW_DELTA,
MINIMUM_ALPHA,
+ EMISSIVE_BRIGHTNESS,
DEFERRED_SHADOW_MATRIX,
DEFERRED_ENV_MAT,
@@ -164,6 +165,13 @@ public:
DEFERRED_LIGHT,
DEFERRED_BLOOM,
DEFERRED_PROJECTION,
+
+ GLOBAL_GAMMA,
+ TEXTURE_GAMMA,
+
+ SPECULAR_COLOR,
+ ENVIRONMENT_INTENSITY,
+
END_RESERVED_UNIFORMS
} eGLSLReservedUniforms;
@@ -176,7 +184,7 @@ public:
void dumpObjectLog(GLhandleARB ret, BOOL warns = TRUE);
BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE);
BOOL validateProgramObject(GLhandleARB obj);
- GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels = -1);
+ GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, boost::unordered_map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1);
// Implemented in the application to actually point to the shader directory.
virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 4909b43e8a..01541026b1 100755
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -342,13 +342,32 @@ S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] =
sizeof(LLVector2), // TYPE_TEXCOORD3,
sizeof(LLColor4U), // TYPE_COLOR,
sizeof(LLColor4U), // TYPE_EMISSIVE, only alpha is used currently
- sizeof(LLVector4), // TYPE_BINORMAL,
+ sizeof(LLVector4), // TYPE_TANGENT,
sizeof(F32), // TYPE_WEIGHT,
sizeof(LLVector4), // TYPE_WEIGHT4,
sizeof(LLVector4), // TYPE_CLOTHWEIGHT,
sizeof(LLVector4), // TYPE_TEXTURE_INDEX (actually exists as position.w), no extra data, but stride is 16 bytes
};
+static std::string vb_type_name[] =
+{
+ "TYPE_VERTEX",
+ "TYPE_NORMAL",
+ "TYPE_TEXCOORD0",
+ "TYPE_TEXCOORD1",
+ "TYPE_TEXCOORD2",
+ "TYPE_TEXCOORD3",
+ "TYPE_COLOR",
+ "TYPE_EMISSIVE",
+ "TYPE_TANGENT",
+ "TYPE_WEIGHT",
+ "TYPE_WEIGHT4",
+ "TYPE_CLOTHWEIGHT",
+ "TYPE_TEXTURE_INDEX",
+ "TYPE_MAX",
+ "TYPE_INDEX",
+};
+
U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] =
{
GL_TRIANGLES,
@@ -523,16 +542,16 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
}
}
- if (sLastMask & MAP_BINORMAL)
+ if (sLastMask & MAP_TANGENT)
{
- if (!(data_mask & MAP_BINORMAL))
+ if (!(data_mask & MAP_TANGENT))
{
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
}
}
- else if (data_mask & MAP_BINORMAL)
+ else if (data_mask & MAP_TANGENT)
{
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@@ -593,8 +612,9 @@ void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, con
glVertexPointer(3, GL_FLOAT, 0, pos[0].mV);
glNormalPointer(GL_FLOAT, 0, norm[0].mV);
}
-
+ LLGLSLShader::startProfile();
glDrawArrays(sGLMode[mode], 0, count);
+ LLGLSLShader::stopProfile(count, mode);
}
//static
@@ -631,7 +651,9 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto
glVertexPointer(3, GL_FLOAT, 16, pos);
}
+ LLGLSLShader::startProfile();
glDrawElements(sGLMode[mode], num_indices, GL_UNSIGNED_SHORT, indicesp);
+ LLGLSLShader::stopProfile(num_indices, mode);
}
void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const
@@ -731,9 +753,14 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
U16* idx = ((U16*) getIndicesPointer())+indices_offset;
stop_glerror();
+ LLGLSLShader::startProfile();
glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT,
idx);
+ LLGLSLShader::stopProfile(count, mode);
stop_glerror();
+
+
+
placeFence();
}
@@ -777,8 +804,10 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
}
stop_glerror();
+ LLGLSLShader::startProfile();
glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT,
((U16*) getIndicesPointer()) + indices_offset);
+ LLGLSLShader::stopProfile(count, mode);
stop_glerror();
placeFence();
}
@@ -820,9 +849,12 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
{
LLFastTimer t2(FTM_GL_DRAW_ARRAYS);
- stop_glerror();
- glDrawArrays(sGLMode[mode], first, count);
- }
+ stop_glerror();
+ LLGLSLShader::startProfile();
+ glDrawArrays(sGLMode[mode], first, count);
+ LLGLSLShader::stopProfile(count, mode);
+ }
+
stop_glerror();
placeFence();
}
@@ -1322,7 +1354,7 @@ void LLVertexBuffer::setupVertexArray()
2, //TYPE_TEXCOORD3,
4, //TYPE_COLOR,
4, //TYPE_EMISSIVE,
- 3, //TYPE_BINORMAL,
+ 4, //TYPE_TANGENT,
1, //TYPE_WEIGHT,
4, //TYPE_WEIGHT4,
4, //TYPE_CLOTHWEIGHT,
@@ -1339,7 +1371,7 @@ void LLVertexBuffer::setupVertexArray()
GL_FLOAT, //TYPE_TEXCOORD3,
GL_UNSIGNED_BYTE, //TYPE_COLOR,
GL_UNSIGNED_BYTE, //TYPE_EMISSIVE,
- GL_FLOAT, //TYPE_BINORMAL,
+ GL_FLOAT, //TYPE_TANGENT,
GL_FLOAT, //TYPE_WEIGHT,
GL_FLOAT, //TYPE_WEIGHT4,
GL_FLOAT, //TYPE_CLOTHWEIGHT,
@@ -1356,7 +1388,7 @@ void LLVertexBuffer::setupVertexArray()
false, //TYPE_TEXCOORD3,
false, //TYPE_COLOR,
false, //TYPE_EMISSIVE,
- false, //TYPE_BINORMAL,
+ false, //TYPE_TANGENT,
false, //TYPE_WEIGHT,
false, //TYPE_WEIGHT4,
false, //TYPE_CLOTHWEIGHT,
@@ -1373,7 +1405,7 @@ void LLVertexBuffer::setupVertexArray()
GL_FALSE, //TYPE_TEXCOORD3,
GL_TRUE, //TYPE_COLOR,
GL_TRUE, //TYPE_EMISSIVE,
- GL_FALSE, //TYPE_BINORMAL,
+ GL_FALSE, //TYPE_TANGENT,
GL_FALSE, //TYPE_WEIGHT,
GL_FALSE, //TYPE_WEIGHT4,
GL_FALSE, //TYPE_CLOTHWEIGHT,
@@ -2038,14 +2070,21 @@ bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 inde
{
return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index, count, map_range);
}
-
+bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
+{
+ return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index, count, map_range);
+}
bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
{
return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index, count, map_range);
}
-bool LLVertexBuffer::getBinormalStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getTangentStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
{
- return VertexBufferStrider<LLVector3,TYPE_BINORMAL>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector3,TYPE_TANGENT>::get(*this, strider, index, count, map_range);
+}
+bool LLVertexBuffer::getTangentStrider(LLStrider<LLVector4a>& strider, S32 index, S32 count, bool map_range)
+{
+ return VertexBufferStrider<LLVector4a,TYPE_TANGENT>::get(*this, strider, index, count, map_range);
}
bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, S32 index, S32 count, bool map_range)
{
@@ -2200,7 +2239,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
if ((data_mask & required_mask) != required_mask)
{
- llerrs << "Shader consumption mismatches data provision." << llendl;
+ llwarns << "Shader consumption mismatches data provision." << llendl;
}
}
}
@@ -2318,6 +2357,14 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
if (gDebugGL && ((data_mask & mTypeMask) != data_mask))
{
+ for (U32 i = 0; i < LLVertexBuffer::TYPE_MAX; ++i)
+ {
+ U32 mask = 1 << i;
+ if (mask & data_mask && !(mask & mTypeMask))
+ { //bit set in data_mask, but not set in mTypeMask
+ llwarns << "Missing required component " << vb_type_name[i] << llendl;
+ }
+ }
llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl;
}
@@ -2347,11 +2394,11 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD1]);
glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr);
}
- if (data_mask & MAP_BINORMAL)
+ if (data_mask & MAP_TANGENT)
{
- S32 loc = TYPE_BINORMAL;
- void* ptr = (void*)(base + mOffsets[TYPE_BINORMAL]);
- glVertexAttribPointerARB(loc, 3,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_BINORMAL], ptr);
+ S32 loc = TYPE_TANGENT;
+ void* ptr = (void*)(base + mOffsets[TYPE_TANGENT]);
+ glVertexAttribPointerARB(loc, 4,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr);
}
if (data_mask & MAP_TEXCOORD0)
{
@@ -2429,10 +2476,10 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1]));
glClientActiveTextureARB(GL_TEXTURE0_ARB);
}
- if (data_mask & MAP_BINORMAL)
+ if (data_mask & MAP_TANGENT)
{
glClientActiveTextureARB(GL_TEXTURE2_ARB);
- glTexCoordPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_BINORMAL], (void*)(base + mOffsets[TYPE_BINORMAL]));
+ glTexCoordPointer(4,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TANGENT], (void*)(base + mOffsets[TYPE_TANGENT]));
glClientActiveTextureARB(GL_TEXTURE0_ARB);
}
if (data_mask & MAP_TEXCOORD0)
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index 11fa4ab6a0..04806c1d8c 100755
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -174,7 +174,7 @@ public:
TYPE_TEXCOORD3,
TYPE_COLOR,
TYPE_EMISSIVE,
- TYPE_BINORMAL,
+ TYPE_TANGENT,
TYPE_WEIGHT,
TYPE_WEIGHT4,
TYPE_CLOTHWEIGHT,
@@ -192,7 +192,7 @@ public:
MAP_COLOR = (1<<TYPE_COLOR),
MAP_EMISSIVE = (1<<TYPE_EMISSIVE),
// These use VertexAttribPointer and should possibly be made generic
- MAP_BINORMAL = (1<<TYPE_BINORMAL),
+ MAP_TANGENT = (1<<TYPE_TANGENT),
MAP_WEIGHT = (1<<TYPE_WEIGHT),
MAP_WEIGHT4 = (1<<TYPE_WEIGHT4),
MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT),
@@ -250,8 +250,10 @@ public:
bool getIndexStrider(LLStrider<U16>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getTangentStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getTangentStrider(LLStrider<LLVector4a>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getTextureIndexStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getEmissiveStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);