Merge remote-tracking branch 'siana/master'
Conflicts: indra/llrender/llvertexbuffer.cpp Resolved: needed two casts for 64bit warning.
This commit is contained in:
@@ -108,9 +108,15 @@ void APIENTRY gl_debug_callback(GLenum source,
|
||||
llwarns << "Severity: " << std::hex << severity << llendl;
|
||||
llwarns << "Message: " << message << llendl;
|
||||
llwarns << "-----------------------" << llendl;
|
||||
if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
|
||||
{
|
||||
llerrs << "Halting on GL Error" << llendl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void parse_glsl_version(S32& major, S32& minor);
|
||||
|
||||
void ll_init_fail_log(std::string filename)
|
||||
{
|
||||
gFailLog.open(filename.c_str());
|
||||
@@ -309,6 +315,7 @@ PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB = NULL;
|
||||
PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB = NULL;
|
||||
PFNGLGETUNIFORMIVARBPROC glGetUniformivARB = NULL;
|
||||
PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB = NULL;
|
||||
PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer = NULL;
|
||||
|
||||
#if LL_WINDOWS
|
||||
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
|
||||
@@ -458,7 +465,8 @@ LLGLManager::LLGLManager() :
|
||||
mDriverVersionMinor(0),
|
||||
mDriverVersionRelease(0),
|
||||
mGLVersion(1.0f),
|
||||
|
||||
mGLSLVersionMajor(0),
|
||||
mGLSLVersionMinor(0),
|
||||
mVRAM(0),
|
||||
mGLMaxVertexRange(0),
|
||||
mGLMaxIndexRange(0)
|
||||
@@ -569,6 +577,29 @@ bool LLGLManager::initGL()
|
||||
|
||||
mGLVersion = mDriverVersionMajor + mDriverVersionMinor * .1f;
|
||||
|
||||
if (mGLVersion >= 2.f)
|
||||
{
|
||||
parse_glsl_version(mGLSLVersionMajor, mGLSLVersionMinor);
|
||||
|
||||
#if LL_DARWIN
|
||||
//never use GLSL greater than 1.20 on OSX
|
||||
if (mGLSLVersionMajor > 1 || mGLSLVersionMinor >= 30)
|
||||
{
|
||||
mGLSLVersionMajor = 1;
|
||||
mGLSLVersionMinor = 20;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mGLVersion >= 3.f && LLImageGL::sCompressTextures)
|
||||
{ //use texture compression
|
||||
glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST);
|
||||
}
|
||||
else
|
||||
{ //GL version is < 3.0, always disable texture compression
|
||||
LLImageGL::sCompressTextures = false;
|
||||
}
|
||||
|
||||
// Trailing space necessary to keep "nVidia Corpor_ati_on" cards
|
||||
// from being recognized as ATI.
|
||||
if (mGLVendor.substr(0,4) == "ATI ")
|
||||
@@ -589,11 +620,8 @@ bool LLGLManager::initGL()
|
||||
#endif // LL_WINDOWS
|
||||
|
||||
#if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS
|
||||
// release 7277 is a point at which we verify that ATI OpenGL
|
||||
// drivers get pretty stable with SL, ~Catalyst 8.2,
|
||||
// for both Win32 and Linux.
|
||||
if (mDriverVersionRelease < 7277 &&
|
||||
mDriverVersionRelease != 0) // 0 == Undetectable driver version - these get to pretend to be new ATI drivers, though that decision may be revisited.
|
||||
// count any pre OpenGL 3.0 implementation as an old driver
|
||||
if (mGLVersion < 3.f)
|
||||
{
|
||||
mATIOldDriver = TRUE;
|
||||
}
|
||||
@@ -1292,6 +1320,7 @@ void LLGLManager::initExtensions()
|
||||
glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4uivARB");
|
||||
glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4usvARB");
|
||||
glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribPointerARB");
|
||||
glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribIPointer");
|
||||
glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glEnableVertexAttribArrayARB");
|
||||
glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDisableVertexAttribArrayARB");
|
||||
glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramStringARB");
|
||||
@@ -2082,6 +2111,55 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void parse_glsl_version(S32& major, S32& minor)
|
||||
{
|
||||
// GL_SHADING_LANGUAGE_VERSION returns a null-terminated string with the format:
|
||||
// <major>.<minor>[.<release>] [<vendor specific>]
|
||||
|
||||
const char* version = (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION);
|
||||
major = 0;
|
||||
minor = 0;
|
||||
|
||||
if( !version )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::string ver_copy( version );
|
||||
S32 len = (S32)strlen( version ); /* Flawfinder: ignore */
|
||||
S32 i = 0;
|
||||
S32 start;
|
||||
// Find the major version
|
||||
start = i;
|
||||
for( ; i < len; i++ )
|
||||
{
|
||||
if( '.' == version[i] )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::string major_str = ver_copy.substr(start,i-start);
|
||||
LLStringUtil::convertToS32(major_str, major);
|
||||
|
||||
if( '.' == version[i] )
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
// Find the minor version
|
||||
start = i;
|
||||
for( ; i < len; i++ )
|
||||
{
|
||||
if( ('.' == version[i]) || isspace(version[i]) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::string minor_str = ver_copy.substr(start,i-start);
|
||||
LLStringUtil::convertToS32(minor_str, minor);
|
||||
}
|
||||
|
||||
LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glh::matrix4f& modelview, const glh::matrix4f& projection, bool apply)
|
||||
{
|
||||
mApply = apply;
|
||||
|
||||
@@ -145,6 +145,8 @@ public:
|
||||
S32 mDriverVersionMinor;
|
||||
S32 mDriverVersionRelease;
|
||||
F32 mGLVersion; // e.g = 1.4
|
||||
S32 mGLSLVersionMajor;
|
||||
S32 mGLSLVersionMinor;
|
||||
std::string mDriverVersionVendorString;
|
||||
|
||||
S32 mVRAM; // VRAM in MB
|
||||
|
||||
@@ -207,6 +207,7 @@ extern PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB;
|
||||
extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB;
|
||||
extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB;
|
||||
extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB;
|
||||
extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;
|
||||
extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB;
|
||||
extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB;
|
||||
extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
|
||||
@@ -466,6 +467,7 @@ extern PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB;
|
||||
extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB;
|
||||
extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB;
|
||||
extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB;
|
||||
extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;
|
||||
extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB;
|
||||
extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB;
|
||||
extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
|
||||
@@ -699,6 +701,7 @@ extern PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB;
|
||||
extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB;
|
||||
extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB;
|
||||
extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB;
|
||||
extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;
|
||||
extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB;
|
||||
extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB;
|
||||
extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
|
||||
|
||||
@@ -149,12 +149,6 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
|
||||
glDeleteObjectARB(mProgramObject);
|
||||
// Create program
|
||||
mProgramObject = glCreateProgramObjectARB();
|
||||
|
||||
static const LLCachedControl<bool> no_texture_indexing("ShyotlUseLegacyTextureBatching",false);
|
||||
if (gGLManager.mGLVersion < 3.1f || no_texture_indexing)
|
||||
{ //force indexed texture channels to 1 if GL version is old (performance improvement for drivers with poor branching shader model support)
|
||||
mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1);
|
||||
}
|
||||
|
||||
//compile new source
|
||||
vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin();
|
||||
@@ -181,8 +175,9 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (gGLManager.mGLVersion < 3.1f || no_texture_indexing)
|
||||
{ //attachShaderFeatures may have set the number of indexed texture channels, so set to 1 again
|
||||
static const LLCachedControl<bool> no_texture_indexing("ShyotlUseLegacyTextureBatching",false);
|
||||
if (gGLManager.mGLVersion < 3.1f || no_texture_indexing)
|
||||
{ //attachShaderFeatures may have set the number of indexed texture channels, so set to 1 again
|
||||
mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ BOOL LLImageGL::sGlobalUseAnisotropic = FALSE;
|
||||
F32 LLImageGL::sLastFrameTime = 0.f;
|
||||
BOOL LLImageGL::sAllowReadBackRaw = FALSE ;
|
||||
LLImageGL* LLImageGL::sDefaultGLTexture = NULL ;
|
||||
bool LLImageGL::sCompressTextures = false;
|
||||
|
||||
std::set<LLImageGL*> LLImageGL::sImageList;
|
||||
|
||||
@@ -489,6 +490,8 @@ void LLImageGL::init(BOOL usemipmaps)
|
||||
mHeight = 0;
|
||||
mCurrentDiscardLevel = -1;
|
||||
|
||||
mAllowCompression = true;
|
||||
|
||||
mTarget = GL_TEXTURE_2D;
|
||||
mBindTarget = LLTexUnit::TT_TEXTURE;
|
||||
mHasMipMaps = false;
|
||||
@@ -720,7 +723,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
|
||||
stop_glerror();
|
||||
}
|
||||
|
||||
LLImageGL::setManualImage(mTarget, gl_level, mFormatInternal, w, h, mFormatPrimary, GL_UNSIGNED_BYTE, (GLvoid*)data_in);
|
||||
LLImageGL::setManualImage(mTarget, gl_level, mFormatInternal, w, h, mFormatPrimary, GL_UNSIGNED_BYTE, (GLvoid*)data_in, mAllowCompression);
|
||||
if (gl_level == 0)
|
||||
{
|
||||
analyzeAlpha(data_in, w, h);
|
||||
@@ -762,7 +765,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
|
||||
LLImageGL::setManualImage(mTarget, 0, mFormatInternal,
|
||||
w, h,
|
||||
mFormatPrimary, mFormatType,
|
||||
data_in);
|
||||
data_in, mAllowCompression);
|
||||
analyzeAlpha(data_in, w, h);
|
||||
stop_glerror();
|
||||
|
||||
@@ -821,7 +824,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
|
||||
stop_glerror();
|
||||
}
|
||||
|
||||
LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data);
|
||||
LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data, mAllowCompression);
|
||||
if (m == 0)
|
||||
{
|
||||
analyzeAlpha(data_in, w, h);
|
||||
@@ -880,7 +883,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
|
||||
}
|
||||
|
||||
LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h,
|
||||
mFormatPrimary, mFormatType, (GLvoid *)data_in);
|
||||
mFormatPrimary, mFormatType, (GLvoid *)data_in, mAllowCompression);
|
||||
analyzeAlpha(data_in, w, h);
|
||||
|
||||
updatePickMask(w, h, data_in);
|
||||
@@ -1039,7 +1042,7 @@ void LLImageGL::deleteTextures(S32 numTextures, U32 *textures, bool immediate)
|
||||
}
|
||||
|
||||
// static
|
||||
void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels)
|
||||
void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression)
|
||||
{
|
||||
bool use_scratch = false;
|
||||
U32* scratch = NULL;
|
||||
@@ -1102,6 +1105,36 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
|
||||
}
|
||||
}
|
||||
|
||||
if (LLImageGL::sCompressTextures && allow_compression)
|
||||
{
|
||||
switch (intformat)
|
||||
{
|
||||
case GL_RGB:
|
||||
case GL_RGB8:
|
||||
intformat = GL_COMPRESSED_RGB;
|
||||
break;
|
||||
case GL_RGBA:
|
||||
case GL_RGBA8:
|
||||
intformat = GL_COMPRESSED_RGBA;
|
||||
break;
|
||||
case GL_LUMINANCE:
|
||||
case GL_LUMINANCE8:
|
||||
intformat = GL_COMPRESSED_LUMINANCE;
|
||||
break;
|
||||
case GL_LUMINANCE_ALPHA:
|
||||
case GL_LUMINANCE8_ALPHA8:
|
||||
intformat = GL_COMPRESSED_LUMINANCE_ALPHA;
|
||||
break;
|
||||
case GL_ALPHA:
|
||||
case GL_ALPHA8:
|
||||
intformat = GL_COMPRESSED_ALPHA;
|
||||
break;
|
||||
default:
|
||||
llwarns << "Could not compress format: " << std::hex << intformat << llendl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
stop_glerror();
|
||||
glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels);
|
||||
stop_glerror();
|
||||
|
||||
@@ -100,12 +100,13 @@ public:
|
||||
|
||||
void setSize(S32 width, S32 height, S32 ncomponents);
|
||||
void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;}
|
||||
void setAllowCompression(bool allow) { mAllowCompression = allow; }
|
||||
|
||||
// These 3 functions currently wrap glGenTextures(), glDeleteTextures(), and glTexImage2D()
|
||||
// for tracking purposes and will be deprecated in the future
|
||||
static void generateTextures(S32 numTextures, U32 *textures);
|
||||
static void deleteTextures(S32 numTextures, U32 *textures, bool immediate = false);
|
||||
static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels);
|
||||
static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression = true);
|
||||
|
||||
BOOL createGLTexture() ;
|
||||
BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE,
|
||||
@@ -202,6 +203,8 @@ private:
|
||||
U16 mHeight;
|
||||
S8 mCurrentDiscardLevel;
|
||||
|
||||
bool mAllowCompression;
|
||||
|
||||
protected:
|
||||
LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps)
|
||||
LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps)
|
||||
@@ -239,6 +242,7 @@ public:
|
||||
static U32 sUniqueCount; // Tracks number of unique texture binds for current frame
|
||||
static BOOL sGlobalUseAnisotropic;
|
||||
static LLImageGL* sDefaultGLTexture ;
|
||||
static bool sCompressTextures; //use GL texture compression
|
||||
|
||||
#if DEBUG_MISS
|
||||
BOOL mMissed; // Missed on last bind?
|
||||
|
||||
@@ -1440,8 +1440,6 @@ void LLRender::loadIdentity()
|
||||
flush();
|
||||
|
||||
{
|
||||
llassert_always(mMatrixMode < NUM_MATRIX_MODES) ;
|
||||
|
||||
mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].make_identity();
|
||||
mMatHash[mMatrixMode]++;
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)
|
||||
|
||||
{
|
||||
clear_glerror();
|
||||
LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false);
|
||||
if (glGetError() != GL_NO_ERROR)
|
||||
{
|
||||
llwarns << "Could not allocate color buffer for render target." << llendl;
|
||||
@@ -237,7 +237,7 @@ bool LLRenderTarget::allocateDepth()
|
||||
U32 internal_type = LLTexUnit::getInternalType(mUsage);
|
||||
stop_glerror();
|
||||
clear_glerror();
|
||||
LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
|
||||
LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false);
|
||||
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
|
||||
}
|
||||
|
||||
|
||||
@@ -543,7 +543,6 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//read in from file
|
||||
LLFILE* file = NULL;
|
||||
|
||||
@@ -572,40 +571,52 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
|
||||
return 0;
|
||||
}
|
||||
|
||||
//we can't have any lines longer than 1024 characters
|
||||
//we can't have any lines longer than 1024 characters
|
||||
//or any shaders longer than 4096 lines... deal - DaveP
|
||||
GLcharARB buff[1024];
|
||||
GLcharARB* text[4096];
|
||||
GLuint count = 0;
|
||||
|
||||
F32 version = gGLManager.mGLVersion;
|
||||
|
||||
//hack to never use GLSL > 1.20 on OSX
|
||||
#if LL_DARWIN
|
||||
version = llmin(version, 2.9f);
|
||||
#endif
|
||||
|
||||
if (version < 2.1f)
|
||||
S32 major_version = gGLManager.mGLSLVersionMajor;
|
||||
S32 minor_version = gGLManager.mGLSLVersionMinor;
|
||||
|
||||
if (major_version == 1 && minor_version < 30)
|
||||
{
|
||||
text[count++] = strdup("#version 110\n");
|
||||
text[count++] = strdup("#define ATTRIBUTE attribute\n");
|
||||
text[count++] = strdup("#define VARYING varying\n");
|
||||
}
|
||||
else if (version < 3.3f)
|
||||
{
|
||||
//set version to 1.20
|
||||
text[count++] = strdup("#version 120\n");
|
||||
text[count++] = strdup("#define FXAA_GLSL_120 1\n");
|
||||
text[count++] = strdup("#define FXAA_FAST_PIXEL_OFFSET 0\n");
|
||||
text[count++] = strdup("#define ATTRIBUTE attribute\n");
|
||||
text[count++] = strdup("#define VARYING varying\n");
|
||||
if (minor_version < 10)
|
||||
{
|
||||
//should NEVER get here -- if major version is 1 and minor version is less than 10,
|
||||
// viewer should never attempt to use shaders, continuing will result in undefined behavior
|
||||
llerrs << "Unsupported GLSL Version." << llendl;
|
||||
}
|
||||
|
||||
if (minor_version <= 19)
|
||||
{
|
||||
text[count++] = strdup("#version 110\n");
|
||||
text[count++] = strdup("#define ATTRIBUTE attribute\n");
|
||||
text[count++] = strdup("#define VARYING varying\n");
|
||||
text[count++] = strdup("#define VARYING_FLAT varying\n");
|
||||
}
|
||||
else if (minor_version <= 29)
|
||||
{
|
||||
//set version to 1.20
|
||||
text[count++] = strdup("#version 120\n");
|
||||
text[count++] = strdup("#define FXAA_GLSL_120 1\n");
|
||||
text[count++] = strdup("#define FXAA_FAST_PIXEL_OFFSET 0\n");
|
||||
text[count++] = strdup("#define ATTRIBUTE attribute\n");
|
||||
text[count++] = strdup("#define VARYING varying\n");
|
||||
text[count++] = strdup("#define VARYING_FLAT varying\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (version < 4.f)
|
||||
if (major_version < 4)
|
||||
{
|
||||
//set version to 1.30
|
||||
text[count++] = strdup("#version 130\n");
|
||||
|
||||
//some implementations of GLSL 1.30 require integer precision be explicitly declared
|
||||
text[count++] = strdup("precision mediump int;\n");
|
||||
text[count++] = strdup("precision highp float;\n");
|
||||
}
|
||||
else
|
||||
{ //set version to 400
|
||||
@@ -621,21 +632,25 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
|
||||
{ //"varying" state is "out" in a vertex program, "in" in a fragment program
|
||||
// ("varying" is deprecated after version 1.20)
|
||||
text[count++] = strdup("#define VARYING out\n");
|
||||
text[count++] = strdup("#define VARYING_FLAT flat out\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
text[count++] = strdup("#define VARYING in\n");
|
||||
text[count++] = strdup("#define VARYING_FLAT flat in\n");
|
||||
}
|
||||
|
||||
//backwards compatibility with legacy texture lookup syntax
|
||||
text[count++] = strdup("#define texture2D texture\n");
|
||||
text[count++] = strdup("#define textureCube texture\n");
|
||||
text[count++] = strdup("#define texture2DLod textureLod\n");
|
||||
text[count++] = strdup("#define shadow2D(a,b) vec2(texture(a,b))\n"); //Shadow lookups only return a single float.
|
||||
|
||||
//Also deprecated:
|
||||
text[count++] = strdup("#define texture2D texture\n");
|
||||
text[count++] = strdup("#define texture2DRect texture\n");
|
||||
text[count++] = strdup("#define shadow2DRect(a,b) vec2(texture(a,b))\n");
|
||||
text[count++] = strdup("#define shadow2D(a,b) vec2(texture(a,b))\n");
|
||||
|
||||
if (major_version > 1 || minor_version >= 40)
|
||||
{ //GLSL 1.40 replaces texture2DRect et al with texture
|
||||
text[count++] = strdup("#define texture2DRect texture\n");
|
||||
text[count++] = strdup("#define shadow2DRect(a,b) vec2(texture(a,b))\n");
|
||||
}
|
||||
}
|
||||
|
||||
//copy preprocessor definitions into buffer
|
||||
@@ -659,22 +674,24 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
|
||||
.
|
||||
uniform sampler2D texN;
|
||||
|
||||
varying float vary_texture_index;
|
||||
VARYING_FLAT ivec4 vary_texture_index;
|
||||
|
||||
vec4 ret = vec4(1,0,1,1);
|
||||
|
||||
vec4 diffuseLookup(vec2 texcoord)
|
||||
{
|
||||
switch (int(vary_texture_index+0.25))
|
||||
switch (vary_texture_index.r))
|
||||
{
|
||||
case 0: return texture2D(tex0, texcoord);
|
||||
case 1: return texture2D(tex1, texcoord);
|
||||
case 2: return texture2D(tex2, texcoord);
|
||||
case 0: ret = texture2D(tex0, texcoord); break;
|
||||
case 1: ret = texture2D(tex1, texcoord); break;
|
||||
case 2: ret = texture2D(tex2, texcoord); break;
|
||||
.
|
||||
.
|
||||
.
|
||||
case N: return texture2D(texN, texcoord);
|
||||
case N: return texture2D(texN, texcoord); break;
|
||||
}
|
||||
|
||||
return vec4(0,0,0,0);
|
||||
return ret;
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -687,7 +704,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
|
||||
|
||||
if (texture_index_channels > 1)
|
||||
{
|
||||
text[count++] = strdup("VARYING float vary_texture_index;\n");
|
||||
text[count++] = strdup("VARYING_FLAT ivec4 vary_texture_index;\n");
|
||||
}
|
||||
|
||||
text[count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n");
|
||||
@@ -699,45 +716,28 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
|
||||
text[count++] = strdup("return texture2D(tex0, texcoord);\n");
|
||||
text[count++] = strdup("}\n");
|
||||
}
|
||||
else if (gGLManager.mGLVersion >= 3.f && !(gGLManager.mIsATI && gGLManager.mGLVersion < 3.3f) )
|
||||
{
|
||||
text[count++] = strdup("\tswitch (int(vary_texture_index+0.25))\n");
|
||||
else if (major_version > 1 || minor_version >= 30)
|
||||
{ //switches are supported in GLSL 1.30 and later
|
||||
text[count++] = strdup("\tvec4 ret = vec4(1,0,1,1);\n");
|
||||
text[count++] = strdup("\tswitch (vary_texture_index.r)\n");
|
||||
text[count++] = strdup("\t{\n");
|
||||
|
||||
//switch body
|
||||
for (S32 i = 0; i < texture_index_channels; ++i)
|
||||
{
|
||||
std::string case_str = llformat("\t\tcase %d: return texture2D(tex%d, texcoord);\n", i, i);
|
||||
std::string case_str = llformat("\t\tcase %d: ret = texture2D(tex%d, texcoord); break;\n", i, i);
|
||||
text[count++] = strdup(case_str.c_str());
|
||||
}
|
||||
|
||||
text[count++] = strdup("\t}\n");
|
||||
text[count++] = strdup("\treturn vec4(1,0,1,1);\n");
|
||||
text[count++] = strdup("\treturn ret;\n");
|
||||
text[count++] = strdup("}\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
//switches aren't supported, make block that looks like:
|
||||
/*
|
||||
int ti = int(vary_texture_index+0.25);
|
||||
if (ti == 0) return texture2D(tex0, texcoord);
|
||||
if (ti == 1) return texture2D(tex1, texcoord);
|
||||
.
|
||||
.
|
||||
.
|
||||
if (ti == N) return texture2D(texN, texcoord);
|
||||
*/
|
||||
|
||||
text[count++] = strdup("int ti = int(vary_texture_index+0.25);\n");
|
||||
for (S32 i = 0; i < texture_index_channels; ++i)
|
||||
{
|
||||
std::string if_str = llformat("if (ti == %d) return texture2D(tex%d, texcoord);\n", i, i);
|
||||
text[count++] = strdup(if_str.c_str());
|
||||
}
|
||||
|
||||
text[count++] = strdup("\treturn vec4(1,0,1,1);\n");
|
||||
text[count++] = strdup("}\n");
|
||||
}
|
||||
{ //should never get here. Indexed texture rendering requires GLSL 1.30 or later
|
||||
// (for passing integers between vertex and fragment shaders)
|
||||
llerrs << "Indexed texture rendering requires GLSL 1.30 or later." << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
//copy file into memory
|
||||
|
||||
@@ -34,12 +34,13 @@
|
||||
#include "llmemtype.h"
|
||||
#include "llrender.h"
|
||||
#include "llvector4a.h"
|
||||
#include "llcontrol.h"
|
||||
#include "llshadermgr.h"
|
||||
#include "llglslshader.h"
|
||||
#include "llmemory.h"
|
||||
#include "llfasttimer.h"
|
||||
|
||||
#define LL_VBO_POOLING 0
|
||||
|
||||
//Next Highest Power Of Two
|
||||
//helper function, returns first number > v that is a power of 2, or v if v is already a power of 2
|
||||
U32 nhpo2(U32 v)
|
||||
@@ -51,6 +52,35 @@ U32 nhpo2(U32 v)
|
||||
return r;
|
||||
}
|
||||
|
||||
//which power of 2 is i?
|
||||
//assumes i is a power of 2 > 0
|
||||
U32 wpo2(U32 i)
|
||||
{
|
||||
llassert(i > 0);
|
||||
llassert(nhpo2(i) == i);
|
||||
|
||||
U32 r = 0;
|
||||
|
||||
while (i >>= 1) ++r;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
const U32 LL_VBO_BLOCK_SIZE = 2048;
|
||||
|
||||
U32 vbo_block_size(U32 size)
|
||||
{ //what block size will fit size?
|
||||
U32 mod = size % LL_VBO_BLOCK_SIZE;
|
||||
return mod == 0 ? size : size + (LL_VBO_BLOCK_SIZE-mod);
|
||||
}
|
||||
|
||||
U32 vbo_block_index(U32 size)
|
||||
{
|
||||
return vbo_block_size(size)/LL_VBO_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
@@ -59,9 +89,13 @@ LLVBOPool LLVertexBuffer::sStreamVBOPool(GL_STREAM_DRAW_ARB, GL_ARRAY_BUFFER_ARB
|
||||
LLVBOPool LLVertexBuffer::sDynamicVBOPool(GL_DYNAMIC_DRAW_ARB, GL_ARRAY_BUFFER_ARB);
|
||||
LLVBOPool LLVertexBuffer::sStreamIBOPool(GL_STREAM_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB);
|
||||
LLVBOPool LLVertexBuffer::sDynamicIBOPool(GL_DYNAMIC_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB);
|
||||
U32 LLVBOPool::sBytesPooled = 0;
|
||||
|
||||
LLPrivateMemoryPool* LLVertexBuffer::sPrivatePoolp = NULL ;
|
||||
U32 LLVBOPool::sBytesPooled = 0;
|
||||
U32 LLVBOPool::sIndexBytesPooled = 0;
|
||||
U32 LLVertexBuffer::sAllocatedIndexBytes = 0;
|
||||
U32 LLVertexBuffer::sIndexCount = 0;
|
||||
|
||||
LLPrivateMemoryPool* LLVertexBuffer::sPrivatePoolp = NULL;
|
||||
U32 LLVertexBuffer::sBindCount = 0;
|
||||
U32 LLVertexBuffer::sSetCount = 0;
|
||||
S32 LLVertexBuffer::sCount = 0;
|
||||
@@ -76,6 +110,7 @@ U32 LLVertexBuffer::sLastMask = 0;
|
||||
bool LLVertexBuffer::sVBOActive = false;
|
||||
bool LLVertexBuffer::sIBOActive = false;
|
||||
U32 LLVertexBuffer::sAllocatedBytes = 0;
|
||||
U32 LLVertexBuffer::sVertexCount = 0;
|
||||
bool LLVertexBuffer::sMapped = false;
|
||||
bool LLVertexBuffer::sUseStreamDraw = true;
|
||||
bool LLVertexBuffer::sUseVAO = false;
|
||||
@@ -136,39 +171,35 @@ public:
|
||||
};
|
||||
|
||||
|
||||
//which power of 2 is i?
|
||||
//assumes i is a power of 2 > 0
|
||||
U32 wpo2(U32 i)
|
||||
{
|
||||
llassert(i > 0);
|
||||
llassert(nhpo2(i) == i);
|
||||
|
||||
U32 r = 0;
|
||||
|
||||
while (i >>= 1) ++r;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
volatile U8* LLVBOPool::allocate(U32& name, U32 size)
|
||||
{
|
||||
llassert(nhpo2(size) == size);
|
||||
llassert(vbo_block_size(size) == size);
|
||||
|
||||
volatile U8* ret = NULL;
|
||||
|
||||
U32 i = wpo2(size);
|
||||
#if LL_VBO_POOLING
|
||||
|
||||
U32 i = vbo_block_index(size);
|
||||
|
||||
if (mFreeList.size() <= i)
|
||||
{
|
||||
mFreeList.resize(i+1);
|
||||
}
|
||||
|
||||
volatile U8* ret = NULL;
|
||||
|
||||
if (mFreeList[i].empty())
|
||||
{
|
||||
//make a new buffer
|
||||
glGenBuffersARB(1, &name);
|
||||
glBindBufferARB(mType, name);
|
||||
LLVertexBuffer::sAllocatedBytes += size;
|
||||
|
||||
if (mType == GL_ARRAY_BUFFER_ARB)
|
||||
{
|
||||
LLVertexBuffer::sAllocatedBytes += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLVertexBuffer::sAllocatedIndexBytes += size;
|
||||
}
|
||||
|
||||
if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)
|
||||
{
|
||||
@@ -179,6 +210,7 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size)
|
||||
{ //always use a true hint of static draw when allocating non-client-backed buffers
|
||||
glBufferDataARB(mType, size, 0, GL_STATIC_DRAW_ARB);
|
||||
}
|
||||
|
||||
glBindBufferARB(mType, 0);
|
||||
}
|
||||
else
|
||||
@@ -186,19 +218,55 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size)
|
||||
name = mFreeList[i].front().mGLName;
|
||||
ret = mFreeList[i].front().mClientData;
|
||||
|
||||
sBytesPooled -= size;
|
||||
if (mType == GL_ARRAY_BUFFER_ARB)
|
||||
{
|
||||
sBytesPooled -= size;
|
||||
}
|
||||
else
|
||||
{
|
||||
sIndexBytesPooled -= size;
|
||||
}
|
||||
|
||||
mFreeList[i].pop_front();
|
||||
}
|
||||
#else //no pooling
|
||||
|
||||
glGenBuffersARB(1, &name);
|
||||
glBindBufferARB(mType, name);
|
||||
|
||||
if (mType == GL_ARRAY_BUFFER_ARB)
|
||||
{
|
||||
LLVertexBuffer::sAllocatedBytes += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLVertexBuffer::sAllocatedIndexBytes += size;
|
||||
}
|
||||
|
||||
if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)
|
||||
{
|
||||
glBufferDataARB(mType, size, 0, mUsage);
|
||||
ret = (U8*) ll_aligned_malloc_16(size);
|
||||
}
|
||||
else
|
||||
{ //always use a true hint of static draw when allocating non-client-backed buffers
|
||||
glBufferDataARB(mType, size, 0, GL_STATIC_DRAW_ARB);
|
||||
}
|
||||
|
||||
glBindBufferARB(mType, 0);
|
||||
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size)
|
||||
{
|
||||
llassert(nhpo2(size) == size);
|
||||
llassert(vbo_block_size(size) == size);
|
||||
|
||||
U32 i = wpo2(size);
|
||||
#if LL_VBO_POOLING
|
||||
|
||||
U32 i = vbo_block_index(size);
|
||||
|
||||
llassert(mFreeList.size() > i);
|
||||
|
||||
@@ -212,9 +280,29 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size)
|
||||
}
|
||||
else
|
||||
{
|
||||
sBytesPooled += size;
|
||||
if (mType == GL_ARRAY_BUFFER_ARB)
|
||||
{
|
||||
sBytesPooled += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
sIndexBytesPooled += size;
|
||||
}
|
||||
mFreeList[i].push_back(rec);
|
||||
}
|
||||
#else //no pooling
|
||||
glDeleteBuffersARB(1, &name);
|
||||
ll_aligned_free_16((U8*) buffer);
|
||||
|
||||
if (mType == GL_ARRAY_BUFFER_ARB)
|
||||
{
|
||||
LLVertexBuffer::sAllocatedBytes -= size;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLVertexBuffer::sAllocatedIndexBytes -= size;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void LLVBOPool::cleanup()
|
||||
@@ -238,8 +326,16 @@ void LLVBOPool::cleanup()
|
||||
|
||||
l.pop_front();
|
||||
|
||||
LLVertexBuffer::sAllocatedBytes -= size;
|
||||
sBytesPooled -= size;
|
||||
if (mType == GL_ARRAY_BUFFER_ARB)
|
||||
{
|
||||
sBytesPooled -= size;
|
||||
LLVertexBuffer::sAllocatedBytes -= size;
|
||||
}
|
||||
else
|
||||
{
|
||||
sIndexBytesPooled -= size;
|
||||
LLVertexBuffer::sAllocatedIndexBytes -= size;
|
||||
}
|
||||
}
|
||||
|
||||
size *= 2;
|
||||
@@ -285,6 +381,12 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
|
||||
{
|
||||
bool error = false;
|
||||
|
||||
if (gGLManager.mGLSLVersionMajor < 2 && gGLManager.mGLSLVersionMinor < 30)
|
||||
{
|
||||
//make sure texture index is disabled
|
||||
data_mask = data_mask & ~MAP_TEXTURE_INDEX;
|
||||
}
|
||||
|
||||
if (LLGLSLShader::sNoFixedFunction)
|
||||
{
|
||||
for (U32 i = 0; i < TYPE_MAX; ++i)
|
||||
@@ -430,7 +532,7 @@ void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, con
|
||||
|
||||
U32 count = pos.size();
|
||||
llassert_always(norm.size() >= pos.size());
|
||||
llassert_always(count > 0) ;
|
||||
llassert_always(count > 0);
|
||||
|
||||
unbind();
|
||||
|
||||
@@ -689,8 +791,8 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
|
||||
//static
|
||||
void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping)
|
||||
{
|
||||
sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject ;
|
||||
sDisableVBOMapping = sEnableVBOs && no_vbo_mapping ;
|
||||
sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject;
|
||||
sDisableVBOMapping = sEnableVBOs && no_vbo_mapping;
|
||||
|
||||
if (!sPrivatePoolp)
|
||||
{
|
||||
@@ -741,8 +843,8 @@ void LLVertexBuffer::cleanupClass()
|
||||
|
||||
if(sPrivatePoolp)
|
||||
{
|
||||
LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp) ;
|
||||
sPrivatePoolp = NULL ;
|
||||
LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp);
|
||||
sPrivatePoolp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -750,25 +852,41 @@ void LLVertexBuffer::cleanupClass()
|
||||
|
||||
S32 LLVertexBuffer::determineUsage(S32 usage)
|
||||
{
|
||||
if (LLRender::sGLCoreProfile)
|
||||
S32 ret_usage = usage;
|
||||
|
||||
if (!sEnableVBOs)
|
||||
{
|
||||
ret_usage = 0;
|
||||
}
|
||||
|
||||
if (ret_usage == GL_STREAM_DRAW_ARB && !sUseStreamDraw)
|
||||
{
|
||||
ret_usage = 0;
|
||||
}
|
||||
|
||||
if (ret_usage == GL_DYNAMIC_DRAW_ARB && sPreferStreamDraw)
|
||||
{
|
||||
ret_usage = GL_STREAM_DRAW_ARB;
|
||||
}
|
||||
|
||||
if (ret_usage == 0 && LLRender::sGLCoreProfile)
|
||||
{ //MUST use VBOs for all rendering
|
||||
if(!usage)
|
||||
return GL_STREAM_DRAW_ARB;
|
||||
ret_usage = GL_STREAM_DRAW_ARB;
|
||||
}
|
||||
else if (!sEnableVBOs || !usage || (!sUseStreamDraw && usage == GL_STREAM_DRAW_ARB))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
//Only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default.
|
||||
//Always use stream_draw VBO if mapping is disabled, or stream is preferred or expected
|
||||
if( sDisableVBOMapping || sPreferStreamDraw || (usage == GL_STREAM_DRAW_ARB))
|
||||
{
|
||||
return GL_STREAM_DRAW_ARB;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GL_DYNAMIC_DRAW_ARB;
|
||||
|
||||
if (ret_usage && ret_usage != GL_STREAM_DRAW_ARB)
|
||||
{ //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default
|
||||
if (sDisableVBOMapping)
|
||||
{ //always use stream draw if VBO mapping is disabled
|
||||
ret_usage = GL_STREAM_DRAW_ARB;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret_usage = GL_DYNAMIC_DRAW_ARB;
|
||||
}
|
||||
}
|
||||
|
||||
return ret_usage;
|
||||
}
|
||||
|
||||
LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
|
||||
@@ -877,7 +995,10 @@ LLVertexBuffer::~LLVertexBuffer()
|
||||
|
||||
mFence = NULL;
|
||||
|
||||
llassert_always(!mMappedData && !mMappedIndexData) ;
|
||||
sVertexCount -= mNumVerts;
|
||||
sIndexCount -= mNumIndices;
|
||||
|
||||
llassert_always(!mMappedData && !mMappedIndexData);
|
||||
};
|
||||
|
||||
void LLVertexBuffer::placeFence() const
|
||||
@@ -908,7 +1029,7 @@ void LLVertexBuffer::waitFence() const
|
||||
|
||||
void LLVertexBuffer::genBuffer(U32 size)
|
||||
{
|
||||
mSize = nhpo2(size);
|
||||
mSize = vbo_block_size(size);
|
||||
|
||||
if (mUsage == GL_STREAM_DRAW_ARB)
|
||||
{
|
||||
@@ -924,7 +1045,7 @@ void LLVertexBuffer::genBuffer(U32 size)
|
||||
|
||||
void LLVertexBuffer::genIndices(U32 size)
|
||||
{
|
||||
mIndicesSize = nhpo2(size);
|
||||
mIndicesSize = vbo_block_size(size);
|
||||
|
||||
if (mUsage == GL_STREAM_DRAW_ARB)
|
||||
{
|
||||
@@ -1089,18 +1210,25 @@ void LLVertexBuffer::updateNumVerts(S32 nverts)
|
||||
|
||||
if (nverts >= 65535)
|
||||
{
|
||||
llwarns << "Vertex buffer overflow!" << llendl;
|
||||
nverts = 65535;
|
||||
// <FS:ND> FIRE-5077; Just print an info if there are more than 0xFFFF, for now just so there is a message in the logs where in older version #vertices would have been capped.
|
||||
|
||||
// llwarns << "Vertex buffer overflow!" << llendl;
|
||||
// nverts = 65535;
|
||||
llinfos << "More vertices than 65535 (#" << nverts << ")" <<llendl;
|
||||
|
||||
// </FS:ND>
|
||||
}
|
||||
|
||||
U32 needed_size = calcOffsets(mTypeMask, mOffsets, nverts);
|
||||
S32 needed_size = calcOffsets(mTypeMask, mOffsets, nverts);
|
||||
|
||||
if (needed_size > (U32)mSize || needed_size <= (U32)mSize/2)
|
||||
if (needed_size > mSize || needed_size <= mSize/2)
|
||||
{
|
||||
createGLBuffer(needed_size);
|
||||
}
|
||||
|
||||
sVertexCount -= mNumVerts;
|
||||
mNumVerts = nverts;
|
||||
sVertexCount += mNumVerts;
|
||||
}
|
||||
|
||||
void LLVertexBuffer::updateNumIndices(S32 nindices)
|
||||
@@ -1109,14 +1237,16 @@ void LLVertexBuffer::updateNumIndices(S32 nindices)
|
||||
|
||||
llassert(nindices >= 0);
|
||||
|
||||
U32 needed_size = sizeof(U16) * nindices;
|
||||
S32 needed_size = sizeof(U16) * nindices;
|
||||
|
||||
if (needed_size > (U32)mIndicesSize || needed_size <= (U32)mIndicesSize/2)
|
||||
if (needed_size > mIndicesSize || needed_size <= mIndicesSize/2)
|
||||
{
|
||||
createGLIndices(needed_size);
|
||||
}
|
||||
|
||||
sIndexCount -= mNumIndices;
|
||||
mNumIndices = nindices;
|
||||
sIndexCount += mNumIndices;
|
||||
}
|
||||
|
||||
void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
|
||||
@@ -1125,11 +1255,21 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
|
||||
|
||||
stop_glerror();
|
||||
|
||||
if (nverts < 0 || nindices < 0 ||
|
||||
nverts > 65536)
|
||||
{
|
||||
// <FS:ND> FIRE-5077; Just print an info if there are more than 0xFFFF, for now just so there is a message in the logs where in older version #vertices would have been capped.
|
||||
|
||||
// if (nverts < 0 || nindices < 0 ||
|
||||
// nverts > 65536)
|
||||
// {
|
||||
// llerrs << "Bad vertex buffer allocation: " << nverts << " : " << nindices << llendl;
|
||||
// }
|
||||
|
||||
if( nverts < 0 || nindices < 0 )
|
||||
llerrs << "Bad vertex buffer allocation: " << nverts << " : " << nindices << llendl;
|
||||
}
|
||||
|
||||
if( nverts > 0xFFFF )
|
||||
llinfos << "More vertices than 65535 (#" << nverts << ")" <<llendl;
|
||||
|
||||
// </FS:ND>
|
||||
|
||||
updateNumVerts(nverts);
|
||||
updateNumIndices(nindices);
|
||||
@@ -1178,7 +1318,7 @@ void LLVertexBuffer::setupVertexArray()
|
||||
1, //TYPE_WEIGHT,
|
||||
4, //TYPE_WEIGHT4,
|
||||
4, //TYPE_CLOTHWEIGHT,
|
||||
1, //TYPE_TEXTURE_INDEX
|
||||
4, //TYPE_TEXTURE_INDEX
|
||||
};
|
||||
|
||||
U32 attrib_type[] =
|
||||
@@ -1195,7 +1335,24 @@ void LLVertexBuffer::setupVertexArray()
|
||||
GL_FLOAT, //TYPE_WEIGHT,
|
||||
GL_FLOAT, //TYPE_WEIGHT4,
|
||||
GL_FLOAT, //TYPE_CLOTHWEIGHT,
|
||||
GL_FLOAT, //TYPE_TEXTURE_INDEX
|
||||
GL_UNSIGNED_BYTE, //TYPE_TEXTURE_INDEX
|
||||
};
|
||||
|
||||
bool attrib_integer[] =
|
||||
{
|
||||
false, //TYPE_VERTEX,
|
||||
false, //TYPE_NORMAL,
|
||||
false, //TYPE_TEXCOORD0,
|
||||
false, //TYPE_TEXCOORD1,
|
||||
false, //TYPE_TEXCOORD2,
|
||||
false, //TYPE_TEXCOORD3,
|
||||
false, //TYPE_COLOR,
|
||||
false, //TYPE_EMISSIVE,
|
||||
false, //TYPE_BINORMAL,
|
||||
false, //TYPE_WEIGHT,
|
||||
false, //TYPE_WEIGHT4,
|
||||
false, //TYPE_CLOTHWEIGHT,
|
||||
true, //TYPE_TEXTURE_INDEX
|
||||
};
|
||||
|
||||
U32 attrib_normalized[] =
|
||||
@@ -1223,7 +1380,21 @@ void LLVertexBuffer::setupVertexArray()
|
||||
if (mTypeMask & (1 << i))
|
||||
{
|
||||
glEnableVertexAttribArrayARB(i);
|
||||
glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i], attrib_normalized[i], sTypeSize[i], reinterpret_cast<void*>(mOffsets[i]));
|
||||
|
||||
if (attrib_integer[i])
|
||||
{
|
||||
#if !LL_DARWIN
|
||||
//glVertexattribIPointer requires GLSL 1.30 or later
|
||||
if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30)
|
||||
{
|
||||
glVertexAttribIPointer(i, attrib_size[i], attrib_type[i], sTypeSize[i], reinterpret_cast<void*>(mOffsets[i]));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i], attrib_normalized[i], sTypeSize[i], reinterpret_cast<void*>(mOffsets[i]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1286,6 +1457,7 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count)
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_VBO_MAP_BUFFER_RANGE("VBO Map Range");
|
||||
static LLFastTimer::DeclareTimer FTM_VBO_MAP_BUFFER("VBO Map");
|
||||
|
||||
// Map for data access
|
||||
volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range)
|
||||
{
|
||||
@@ -1420,16 +1592,16 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo
|
||||
log_glerror();
|
||||
|
||||
//check the availability of memory
|
||||
LLMemory::logMemoryInfo(true) ;
|
||||
LLMemory::logMemoryInfo(true);
|
||||
|
||||
if(mMappable)
|
||||
{
|
||||
//--------------------
|
||||
//print out more debug info before crash
|
||||
llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ;
|
||||
GLint size ;
|
||||
glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ;
|
||||
llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ;
|
||||
llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl;
|
||||
GLint size;
|
||||
glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size);
|
||||
llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl;
|
||||
//--------------------
|
||||
|
||||
GLint buff;
|
||||
@@ -1444,7 +1616,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo
|
||||
}
|
||||
else
|
||||
{
|
||||
llerrs << "memory allocation for vertex data failed." << llendl ;
|
||||
llerrs << "memory allocation for vertex data failed." << llendl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1598,7 +1770,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
|
||||
if (!mMappedIndexData)
|
||||
{
|
||||
log_glerror();
|
||||
LLMemory::logMemoryInfo(true) ;
|
||||
LLMemory::logMemoryInfo(true);
|
||||
|
||||
if(mMappable)
|
||||
{
|
||||
@@ -1613,7 +1785,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
|
||||
}
|
||||
else
|
||||
{
|
||||
llerrs << "memory allocation for Index data failed. " << llendl ;
|
||||
llerrs << "memory allocation for Index data failed. " << llendl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1644,10 +1816,10 @@ void LLVertexBuffer::unmapBuffer()
|
||||
LLMemType mt2(LLMemType::MTYPE_VERTEX_UNMAP_BUFFER);
|
||||
if (!useVBOs())
|
||||
{
|
||||
return ; //nothing to unmap
|
||||
return; //nothing to unmap
|
||||
}
|
||||
|
||||
bool updated_all = false ;
|
||||
bool updated_all = false;
|
||||
|
||||
if (mMappedData && mVertexLocked)
|
||||
{
|
||||
@@ -1778,10 +1950,10 @@ void LLVertexBuffer::unmapBuffer()
|
||||
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
|
||||
stop_glerror();
|
||||
|
||||
mMappedIndexData = NULL ;
|
||||
mMappedIndexData = NULL;
|
||||
}
|
||||
|
||||
mIndexLocked = false ;
|
||||
mIndexLocked = false;
|
||||
sMappedCount--;
|
||||
}
|
||||
|
||||
@@ -1832,7 +2004,7 @@ template <class T,S32 type> struct VertexBufferStrider
|
||||
}
|
||||
else
|
||||
{
|
||||
llerrs << "VertexBufferStrider could not find valid vertex data." << llendl;
|
||||
llwarns << "VertexBufferStrider could not find valid vertex data." << llendl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -2204,11 +2376,14 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
|
||||
void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]);
|
||||
glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
|
||||
}
|
||||
if (data_mask & MAP_TEXTURE_INDEX)
|
||||
if (data_mask & MAP_TEXTURE_INDEX &&
|
||||
(gGLManager.mGLSLVersionMajor >= 2 || gGLManager.mGLSLVersionMinor >= 30)) //indexed texture rendering requires GLSL 1.30 or later
|
||||
{
|
||||
#if !LL_DARWIN
|
||||
S32 loc = TYPE_TEXTURE_INDEX;
|
||||
void *ptr = (void*) (base + mOffsets[TYPE_VERTEX] + 12);
|
||||
glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
|
||||
glVertexAttribIPointer(loc, 4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
|
||||
#endif
|
||||
}
|
||||
if (data_mask & MAP_VERTEX)
|
||||
{
|
||||
|
||||
@@ -55,14 +55,15 @@ class LLVBOPool
|
||||
{
|
||||
public:
|
||||
static U32 sBytesPooled;
|
||||
|
||||
static U32 sIndexBytesPooled;
|
||||
|
||||
LLVBOPool(U32 vboUsage, U32 vboType)
|
||||
: mUsage(vboUsage)
|
||||
, mType(vboType)
|
||||
{}
|
||||
|
||||
const U32 mUsage;
|
||||
U32 mType;
|
||||
const U32 mType;
|
||||
|
||||
//size MUST be a power of 2
|
||||
volatile U8* allocate(U32& name, U32 size);
|
||||
@@ -93,7 +94,7 @@ public:
|
||||
|
||||
//============================================================================
|
||||
// base class
|
||||
class LLPrivateMemoryPool ;
|
||||
class LLPrivateMemoryPool;
|
||||
class LLVertexBuffer : public LLRefCount
|
||||
{
|
||||
public:
|
||||
@@ -280,7 +281,9 @@ protected:
|
||||
S32 mSize;
|
||||
S32 mIndicesSize;
|
||||
U32 mTypeMask;
|
||||
S32 mUsage; // GL usage
|
||||
|
||||
const S32 mUsage; // GL usage
|
||||
|
||||
U32 mGLBuffer; // GL VBO handle
|
||||
U32 mGLIndices; // GL IBO handle
|
||||
U32 mGLArray; // GL VAO handle
|
||||
@@ -296,6 +299,7 @@ protected:
|
||||
U32 mEmpty : 1; // if true, client buffer is empty (or NULL). Old values have been discarded.
|
||||
|
||||
mutable bool mMappable; // if true, use memory mapping to upload data (otherwise doublebuffer and use glBufferSubData)
|
||||
|
||||
S32 mOffsets[TYPE_MAX];
|
||||
|
||||
std::vector<MappedRegion> mMappedVertexRegions;
|
||||
@@ -309,7 +313,7 @@ protected:
|
||||
static S32 determineUsage(S32 usage);
|
||||
|
||||
private:
|
||||
static LLPrivateMemoryPool* sPrivatePoolp ;
|
||||
static LLPrivateMemoryPool* sPrivatePoolp;
|
||||
|
||||
public:
|
||||
static S32 sCount;
|
||||
@@ -329,6 +333,9 @@ public:
|
||||
static bool sIBOActive;
|
||||
static U32 sLastMask;
|
||||
static U32 sAllocatedBytes;
|
||||
static U32 sAllocatedIndexBytes;
|
||||
static U32 sVertexCount;
|
||||
static U32 sIndexCount;
|
||||
static U32 sBindCount;
|
||||
static U32 sSetCount;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user