diff options
Diffstat (limited to 'indra/llrender')
-rw-r--r-- | indra/llrender/llcubemap.cpp | 12 | ||||
-rw-r--r-- | indra/llrender/llfontgl.cpp | 3 | ||||
-rw-r--r-- | indra/llrender/llgl.cpp | 68 | ||||
-rw-r--r-- | indra/llrender/llgl.h | 2 | ||||
-rw-r--r-- | indra/llrender/llglheaders.h | 39 | ||||
-rw-r--r-- | indra/llrender/llglslshader.cpp | 30 | ||||
-rw-r--r-- | indra/llrender/llglslshader.h | 12 | ||||
-rw-r--r-- | indra/llrender/llimagegl.cpp | 16 | ||||
-rw-r--r-- | indra/llrender/llrender.cpp | 80 | ||||
-rw-r--r-- | indra/llrender/llrender.h | 3 | ||||
-rw-r--r-- | indra/llrender/llrendertarget.cpp | 47 | ||||
-rw-r--r-- | indra/llrender/llrendertarget.h | 14 | ||||
-rw-r--r-- | indra/llrender/llshadermgr.cpp | 148 | ||||
-rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 270 | ||||
-rw-r--r-- | indra/llrender/llvertexbuffer.h | 17 |
15 files changed, 626 insertions, 135 deletions
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index fb22d7f1f5..1b10354c22 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -259,7 +259,7 @@ void LLCubeMap::setMatrix(S32 stage) if (mMatrixStage < 0) return; - if (stage > 0) + //if (stage > 0) { gGL.getTexUnit(stage)->activate(); } @@ -278,17 +278,17 @@ void LLCubeMap::setMatrix(S32 stage) glLoadMatrixf((F32 *)trans.mMatrix); glMatrixMode(GL_MODELVIEW); - if (stage > 0) + /*if (stage > 0) { gGL.getTexUnit(0)->activate(); - } + }*/ } void LLCubeMap::restoreMatrix() { if (mMatrixStage < 0) return; - if (mMatrixStage > 0) + //if (mMatrixStage > 0) { gGL.getTexUnit(mMatrixStage)->activate(); } @@ -296,10 +296,10 @@ void LLCubeMap::restoreMatrix() glPopMatrix(); glMatrixMode(GL_MODELVIEW); - if (mMatrixStage > 0) + /*if (mMatrixStage > 0) { gGL.getTexUnit(0)->activate(); - } + }*/ } void LLCubeMap::setReflection (void) diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 180ae4dfa6..607473d416 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -189,6 +189,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons origin.mV[VX] -= llround((F32)sCurOrigin.mX) - (sCurOrigin.mX); origin.mV[VY] -= llround((F32)sCurOrigin.mY) - (sCurOrigin.mY); + // Depth translation, so that floating text appears 'inworld' + // and is correclty occluded. + gGL.translatef(0.f,0.f,sCurOrigin.mZ); S32 chars_drawn = 0; S32 i; diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index a3aed4dd8a..4e3cfb9c8a 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -48,6 +48,7 @@ #include "llstacktrace.h" #include "llglheaders.h" +#include "llglslshader.h" #ifdef _DEBUG //#define GL_STATE_VERIFY @@ -128,9 +129,21 @@ PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB = NULL; PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB = NULL; // GL_ARB_map_buffer_range -PFNGLMAPBUFFERRANGEPROC glMapBufferRange; -PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange; - +PFNGLMAPBUFFERRANGEPROC glMapBufferRange = NULL; +PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange = NULL; + +// GL_ARB_sync +PFNGLFENCESYNCPROC glFenceSync = NULL; +PFNGLISSYNCPROC glIsSync = NULL; +PFNGLDELETESYNCPROC glDeleteSync = NULL; +PFNGLCLIENTWAITSYNCPROC glClientWaitSync = NULL; +PFNGLWAITSYNCPROC glWaitSync = NULL; +PFNGLGETINTEGER64VPROC glGetInteger64v = NULL; +PFNGLGETSYNCIVPROC glGetSynciv = NULL; + +// GL_APPLE_flush_buffer_range +PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE = NULL; +PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE = NULL; // vertex object prototypes PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI = NULL; @@ -334,9 +347,10 @@ LLGLManager::LLGLManager() : mHasFramebufferObject(FALSE), mMaxSamples(0), mHasBlendFuncSeparate(FALSE), - + mHasSync(FALSE), mHasVertexBufferObject(FALSE), mHasMapBufferRange(FALSE), + mHasFlushBufferRange(FALSE), mHasPBuffer(FALSE), mHasShaderObjects(FALSE), mHasVertexShader(FALSE), @@ -568,6 +582,13 @@ bool LLGLManager::initGL() glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords); } +#if LL_WINDOWS + if (mIsATI) + { //using multisample textures on ATI results in black screen for some reason + mHasTextureMultisample = FALSE; + } +#endif + if (mHasFramebufferObject) { glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples); @@ -767,7 +788,9 @@ void LLGLManager::initExtensions() mHasOcclusionQuery = ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts); mHasOcclusionQuery2 = ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts); mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_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); // mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad #ifdef GL_ARB_framebuffer_object @@ -962,6 +985,16 @@ void LLGLManager::initExtensions() mHasVertexBufferObject = FALSE; } } + if (mHasSync) + { + glFenceSync = (PFNGLFENCESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glFenceSync"); + glIsSync = (PFNGLISSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glIsSync"); + glDeleteSync = (PFNGLDELETESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteSync"); + glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glClientWaitSync"); + glWaitSync = (PFNGLWAITSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glWaitSync"); + glGetInteger64v = (PFNGLGETINTEGER64VPROC) GLH_EXT_GET_PROC_ADDRESS("glGetInteger64v"); + glGetSynciv = (PFNGLGETSYNCIVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetSynciv"); + } if (mHasMapBufferRange) { glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glMapBufferRange"); @@ -1347,6 +1380,8 @@ void LLGLState::checkStates(const std::string& msg) glGetIntegerv(GL_BLEND_SRC, &src); glGetIntegerv(GL_BLEND_DST, &dst); + stop_glerror(); + BOOL error = FALSE; if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA) @@ -1367,7 +1402,9 @@ void LLGLState::checkStates(const std::string& msg) { LLGLenum state = iter->first; LLGLboolean cur_state = iter->second; + stop_glerror(); LLGLboolean gl_state = glIsEnabled(state); + stop_glerror(); if(cur_state != gl_state) { dumpStates(); @@ -1392,11 +1429,11 @@ void LLGLState::checkStates(const std::string& msg) void LLGLState::checkTextureChannels(const std::string& msg) { +#if 0 if (!gDebugGL) { return; } - stop_glerror(); GLint activeTexture; @@ -1562,6 +1599,7 @@ void LLGLState::checkTextureChannels(const std::string& msg) LL_GL_ERRS << "GL texture state corruption detected. " << msg << LL_ENDL; } } +#endif } void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) @@ -1678,7 +1716,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) } } - if (glIsEnabled(GL_TEXTURE_2D)) + /*if (glIsEnabled(GL_TEXTURE_2D)) { if (!(data_mask & 0x0008)) { @@ -1701,7 +1739,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) gFailLog << "GL does not have GL_TEXTURE_2D enabled on channel 1." << std::endl; } } - } + }*/ glClientActiveTextureARB(GL_TEXTURE0_ARB); gGL.getTexUnit(0)->activate(); @@ -1744,6 +1782,16 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) LLGLState::LLGLState(LLGLenum state, S32 enabled) : mState(state), mWasEnabled(FALSE), mIsEnabled(FALSE) { + if (LLGLSLShader::sNoFixedFunction) + { //always disable state that's deprecated post GL 3.0 + switch (state) + { + case GL_ALPHA_TEST: + enabled = 0; + break; + } + } + stop_glerror(); if (state) { @@ -2103,8 +2151,7 @@ void LLGLNamePool::release(GLuint name) void LLGLNamePool::upkeepPools() { LLMemType mt(LLMemType::MTYPE_UPKEEP_POOLS); - tracker_t::LLInstanceTrackerScopedGuard guard; - for (tracker_t::instance_iter iter = guard.beginInstances(); iter != guard.endInstances(); ++iter) + for (tracker_t::instance_iter iter = beginInstances(); iter != endInstances(); ++iter) { LLGLNamePool & pool = *iter; pool.upkeep(); @@ -2114,8 +2161,7 @@ void LLGLNamePool::upkeepPools() //static void LLGLNamePool::cleanupPools() { - tracker_t::LLInstanceTrackerScopedGuard guard; - for (tracker_t::instance_iter iter = guard.beginInstances(); iter != guard.endInstances(); ++iter) + for (tracker_t::instance_iter iter = beginInstances(); iter != endInstances(); ++iter) { LLGLNamePool & pool = *iter; pool.cleanup(); diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index d1bee00161..d736133f3f 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -88,7 +88,9 @@ public: // ARB Extensions BOOL mHasVertexBufferObject; + BOOL mHasSync; BOOL mHasMapBufferRange; + BOOL mHasFlushBufferRange; BOOL mHasPBuffer; BOOL mHasShaderObjects; BOOL mHasVertexShader; diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index f35f329f00..851a75629e 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -68,6 +68,19 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB; extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB; extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB; +// GL_ARB_sync +extern PFNGLFENCESYNCPROC glFenceSync; +extern PFNGLISSYNCPROC glIsSync; +extern PFNGLDELETESYNCPROC glDeleteSync; +extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync; +extern PFNGLWAITSYNCPROC glWaitSync; +extern PFNGLGETINTEGER64VPROC glGetInteger64v; +extern PFNGLGETSYNCIVPROC glGetSynciv; + +// GL_APPLE_flush_buffer_range +extern PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE; +extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE; + // GL_ARB_map_buffer_range extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange; @@ -310,6 +323,19 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB; extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB; extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB; +// GL_ARB_sync +extern PFNGLFENCESYNCPROC glFenceSync; +extern PFNGLISSYNCPROC glIsSync; +extern PFNGLDELETESYNCPROC glDeleteSync; +extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync; +extern PFNGLWAITSYNCPROC glWaitSync; +extern PFNGLGETINTEGER64VPROC glGetInteger64v; +extern PFNGLGETSYNCIVPROC glGetSynciv; + +// GL_APPLE_flush_buffer_range +extern PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE; +extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE; + // GL_ARB_map_buffer_range extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange; @@ -519,6 +545,19 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB; extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB; extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB; +// GL_ARB_sync +extern PFNGLFENCESYNCPROC glFenceSync; +extern PFNGLISSYNCPROC glIsSync; +extern PFNGLDELETESYNCPROC glDeleteSync; +extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync; +extern PFNGLWAITSYNCPROC glWaitSync; +extern PFNGLGETINTEGER64VPROC glGetInteger64v; +extern PFNGLGETSYNCIVPROC glGetSynciv; + +// GL_APPLE_flush_buffer_range +extern PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE; +extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE; + // GL_ARB_map_buffer_range extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange; diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 8e99f62de6..f51d83abe4 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -49,6 +49,12 @@ using std::make_pair; using std::string; GLhandleARB LLGLSLShader::sCurBoundShader = 0; +LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL; +bool LLGLSLShader::sNoFixedFunction = false; + +//UI shader -- declared here so llui_libtest will link properly +LLGLSLShader gUIProgram; +LLGLSLShader gSolidColorProgram; BOOL shouldChange(const LLVector4& v1, const LLVector4& v2) { @@ -58,7 +64,8 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2) LLShaderFeatures::LLShaderFeatures() : calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false), hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false), -hasGamma(false), hasLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false) +hasGamma(false), hasLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false), +hasAlphaMask(false) { } @@ -109,6 +116,11 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes, // Create program mProgramObject = glCreateProgramObjectARB(); + if (gGLManager.mGLVersion < 3.1f) + { //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(); for ( ; fileIter != mShaderFiles.end(); fileIter++ ) @@ -131,6 +143,11 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes, return FALSE; } + if (gGLManager.mGLVersion < 3.1f) + { //attachShaderFeatures may have set the number of indexed texture channels, so set to 1 again + mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1); + } + // Map attributes and uniforms if (success) { @@ -366,10 +383,12 @@ BOOL LLGLSLShader::link(BOOL suppress_errors) void LLGLSLShader::bind() { + gGL.flush(); if (gGLManager.mHasShaderObjects) { glUseProgramObjectARB(mProgramObject); sCurBoundShader = mProgramObject; + sCurBoundShaderPtr = this; if (mUniformsDirty) { LLShaderMgr::instance()->updateShaderUniforms(this); @@ -380,6 +399,7 @@ void LLGLSLShader::bind() void LLGLSLShader::unbind() { + gGL.flush(); if (gGLManager.mHasShaderObjects) { stop_glerror(); @@ -393,6 +413,7 @@ void LLGLSLShader::unbind() } glUseProgramObjectARB(0); sCurBoundShader = 0; + sCurBoundShaderPtr = NULL; stop_glerror(); } } @@ -401,6 +422,7 @@ void LLGLSLShader::bindNoShader(void) { glUseProgramObjectARB(0); sCurBoundShader = 0; + sCurBoundShaderPtr = NULL; } S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode) @@ -962,3 +984,9 @@ void LLGLSLShader::vertexAttrib4fv(U32 index, GLfloat* v) glVertexAttrib4fvARB(mAttribute[index], v); } } + +void LLGLSLShader::setAlphaRange(F32 minimum, F32 maximum) +{ + uniform1f("minimum_alpha", minimum); + uniform1f("maximum_alpha", maximum); +} diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 4922eb6d67..558ea66b50 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -47,6 +47,7 @@ public: bool hasGamma; S32 mIndexedTextureChannels; bool disableTextureIndex; + bool hasAlphaMask; // char numLights; @@ -67,6 +68,9 @@ public: LLGLSLShader(); static GLhandleARB sCurBoundShader; + static LLGLSLShader* sCurBoundShaderPtr; + + static bool sNoFixedFunction; void unload(); BOOL createShader(std::vector<std::string> * attributes, @@ -104,6 +108,8 @@ public: void uniformMatrix3fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v); void uniformMatrix4fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v); + void setAlphaRange(F32 minimum, F32 maximum); + void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); void vertexAttrib4fv(U32 index, GLfloat* v); @@ -141,4 +147,10 @@ public: std::string mName; }; +//UI shader (declared here so llui_libtest will link properly) +extern LLGLSLShader gUIProgram; +//output vec4(color.rgb,color.a*tex0[tc0].a) +extern LLGLSLShader gSolidColorProgram; + + #endif diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 60a5962234..7188b0fa44 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1414,6 +1414,8 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre void LLImageGL::deleteDeadTextures() { + bool reset = false; + while (!sDeadTextureList.empty()) { GLuint tex = sDeadTextureList.front(); @@ -1422,16 +1424,26 @@ void LLImageGL::deleteDeadTextures() { LLTexUnit* tex_unit = gGL.getTexUnit(i); - if (tex_unit->getCurrTexture() == tex) + if (tex_unit && tex_unit->getCurrTexture() == tex) { tex_unit->unbind(tex_unit->getCurrType()); stop_glerror(); + + if (i > 0) + { + reset = true; + } } } glDeleteTextures(1, &tex); stop_glerror(); } + + if (reset) + { + gGL.getTexUnit(0)->activate(); + } } void LLImageGL::destroyGLTexture() @@ -1875,6 +1887,7 @@ BOOL LLImageGL::getMask(const LLVector2 &tc) void LLImageGL::setCategory(S32 category) { +#if 0 //turn this off temporarily because it is not in use now. if(!gAuditTexture) { return ; @@ -1895,6 +1908,7 @@ void LLImageGL::setCategory(S32 category) mCategory = -1 ; } } +#endif } //for debug use diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 6a3f186531..edcc47aa14 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -46,6 +46,7 @@ S32 gGLViewport[4]; U32 LLRender::sUICalls = 0; U32 LLRender::sUIVerts = 0; +U32 LLTexUnit::sWhiteTexture = 0; static const U32 LL_NUM_TEXTURE_LAYERS = 32; static const U32 LL_NUM_LIGHT_UNITS = 8; @@ -126,7 +127,8 @@ void LLTexUnit::refreshState(void) // Per apple spec, don't call glEnable/glDisable when index exceeds max texture units // http://www.mailinglistarchive.com/html/mac-opengl@lists.apple.com/2008-07/msg00653.html // - bool enableDisable = (mIndex < gGLManager.mNumTextureUnits) && mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE; + bool enableDisable = !LLGLSLShader::sNoFixedFunction && + (mIndex < gGLManager.mNumTextureUnits) && mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE; if (mCurrTexType != TT_NONE) { @@ -184,7 +186,8 @@ void LLTexUnit::enable(eTextureType type) mCurrTexType = type; gGL.flush(); - if (type != LLTexUnit::TT_MULTISAMPLE_TEXTURE && + if (!LLGLSLShader::sNoFixedFunction && + type != LLTexUnit::TT_MULTISAMPLE_TEXTURE && mIndex < gGLManager.mNumTextureUnits) { glEnable(sGLTextureType[type]); @@ -201,7 +204,8 @@ void LLTexUnit::disable(void) activate(); unbind(mCurrTexType); gGL.flush(); - if (mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE && + if (!LLGLSLShader::sNoFixedFunction && + mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE && mIndex < gGLManager.mNumTextureUnits) { glDisable(sGLTextureType[mCurrTexType]); @@ -294,7 +298,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind) glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture); texture->updateBindStats(texture->mTextureMemory); mHasMipMaps = texture->mHasMipMaps; - if (mIndex == 0 && texture->mTexOptionsDirty) + if (texture->mTexOptionsDirty) { texture->mTexOptionsDirty = false; setTextureAddressMode(texture->mAddressMode); @@ -403,7 +407,14 @@ void LLTexUnit::unbind(eTextureType type) activate(); mCurrTexture = 0; - glBindTexture(sGLTextureType[type], 0); + if (LLGLSLShader::sNoFixedFunction && type == LLTexUnit::TT_TEXTURE) + { + glBindTexture(sGLTextureType[type], sWhiteTexture); + } + else + { + glBindTexture(sGLTextureType[type], 0); + } stop_glerror(); } } @@ -474,6 +485,11 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio void LLTexUnit::setTextureBlendType(eTextureBlendType type) { + if (LLGLSLShader::sNoFixedFunction) + { //texture blend type means nothing when using shaders + return; + } + if (mIndex < 0) return; // Do nothing if it's already correctly set. @@ -594,6 +610,11 @@ GLint LLTexUnit::getTextureSourceType(eTextureBlendSrc src, bool isAlpha) void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2, bool isAlpha) { + if (LLGLSLShader::sNoFixedFunction) + { //register combiners do nothing when not using fixed function + return; + } + if (mIndex < 0) return; activate(); @@ -906,13 +927,7 @@ LLRender::LLRender() mMode(LLRender::TRIANGLES), mCurrTextureUnitIndex(0), mMaxAnisotropy(0.f) -{ - mBuffer = new LLVertexBuffer(immediate_mask, 0); - mBuffer->allocateBuffer(4096, 0, TRUE); - mBuffer->getVertexStrider(mVerticesp); - mBuffer->getTexCoord0Strider(mTexcoordsp); - mBuffer->getColorStrider(mColorsp); - +{ mTexUnits.reserve(LL_NUM_TEXTURE_LAYERS); for (U32 i = 0; i < LL_NUM_TEXTURE_LAYERS; i++) { @@ -943,6 +958,17 @@ LLRender::~LLRender() shutdown(); } +void LLRender::init() +{ + llassert_always(mBuffer.isNull()) ; + + mBuffer = new LLVertexBuffer(immediate_mask, 0); + mBuffer->allocateBuffer(4096, 0, TRUE); + mBuffer->getVertexStrider(mVerticesp); + mBuffer->getTexCoord0Strider(mTexcoordsp); + mBuffer->getColorStrider(mColorsp); +} + void LLRender::shutdown() { for (U32 i = 0; i < mTexUnits.size(); i++) @@ -958,6 +984,7 @@ void LLRender::shutdown() delete mLightState[i]; } mLightState.clear(); + mBuffer = NULL ; } void LLRender::refreshState(void) @@ -1147,6 +1174,11 @@ void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value) { flush(); + if (LLGLSLShader::sNoFixedFunction) + { //glAlphaFunc is deprecated in OpenGL 3.3 + return; + } + if (mCurrAlphaFunc != func || mCurrAlphaFuncVal != value) { @@ -1161,6 +1193,30 @@ void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value) glAlphaFunc(sGLCompareFunc[func], value); } } + + if (gDebugGL) + { //make sure cached state is correct + GLint cur_func = 0; + glGetIntegerv(GL_ALPHA_TEST_FUNC, &cur_func); + + if (func == CF_DEFAULT) + { + func = CF_GREATER; + } + + if (cur_func != sGLCompareFunc[func]) + { + llerrs << "Alpha test function corrupted!" << llendl; + } + + F32 ref = 0.f; + glGetFloatv(GL_ALPHA_TEST_REF, &ref); + + if (ref != value) + { + llerrs << "Alpha test value corrupted!" << llendl; + } + } } void LLRender::blendFunc(eBlendFactor sfactor, eBlendFactor dfactor) diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 41e7b35341..8f7ee30d87 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -52,6 +52,8 @@ class LLTexUnit { friend class LLRender; public: + static U32 sWhiteTexture; + typedef enum { TT_TEXTURE = 0, // Standard 2D Texture @@ -308,6 +310,7 @@ public: LLRender(); ~LLRender(); + void init() ; void shutdown(); // Refreshes renderer state to the cached values diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index b6463309e1..8c0d3592df 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -72,11 +72,11 @@ LLRenderTarget::~LLRenderTarget() release(); } -void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples) +bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples) { stop_glerror(); - release(); + stop_glerror(); mResX = resx; mResY = resy; @@ -103,9 +103,11 @@ void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo { if (depth) { - stop_glerror(); - allocateDepth(); - stop_glerror(); + if (!allocateDepth()) + { + llwarns << "Failed to allocate depth buffer for render target." << llendl; + return false; + } } glGenFramebuffers(1, (GLuint *) &mFBO); @@ -131,14 +133,14 @@ void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo stop_glerror(); } - addColorAttachment(color_fmt); + return addColorAttachment(color_fmt); } -void LLRenderTarget::addColorAttachment(U32 color_fmt) +bool LLRenderTarget::addColorAttachment(U32 color_fmt) { if (color_fmt == 0) { - return; + return true; } U32 offset = mTex.size(); @@ -158,14 +160,26 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt) #ifdef GL_ARB_texture_multisample if (mSamples > 1) { + clear_glerror(); glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, color_fmt, mResX, mResY, GL_TRUE); + if (glGetError() != GL_NO_ERROR) + { + llwarns << "Could not allocate multisample color buffer for render target." << llendl; + return false; + } } else #else llassert_always(mSamples <= 1); #endif { + clear_glerror(); LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + if (glGetError() != GL_NO_ERROR) + { + llwarns << "Could not allocate color buffer for render target." << llendl; + return false; + } } stop_glerror(); @@ -217,15 +231,18 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt) flush(); } + return true; } -void LLRenderTarget::allocateDepth() +bool LLRenderTarget::allocateDepth() { if (mStencil) { //use render buffers where stencil buffers are in play glGenRenderbuffers(1, (GLuint *) &mDepth); glBindRenderbuffer(GL_RENDERBUFFER, mDepth); + stop_glerror(); + clear_glerror(); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mResX, mResY); glBindRenderbuffer(GL_RENDERBUFFER, 0); } @@ -237,17 +254,29 @@ void LLRenderTarget::allocateDepth() { U32 internal_type = LLTexUnit::getInternalType(mUsage); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + stop_glerror(); + clear_glerror(); LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); } #ifdef GL_ARB_texture_multisample else { + stop_glerror(); + clear_glerror(); glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, GL_DEPTH_COMPONENT32, mResX, mResY, GL_TRUE); } #else llassert_always(mSamples <= 1); #endif } + + if (glGetError() != GL_NO_ERROR) + { + llwarns << "Unable to allocate depth buffer for render target." << llendl; + return false; + } + + return true; } void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index 094b58b562..dea1de12d8 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -66,30 +66,30 @@ public: static bool sUseFBO; LLRenderTarget(); - virtual ~LLRenderTarget(); + ~LLRenderTarget(); //allocate resources for rendering //must be called before use //multiple calls will release previously allocated resources - void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0); + bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0); //add color buffer attachment //limit of 4 color attachments per render target - virtual void addColorAttachment(U32 color_fmt); + bool addColorAttachment(U32 color_fmt); //allocate a depth texture - virtual void allocateDepth(); + bool allocateDepth(); //share depth buffer with provided render target - virtual void shareDepthBuffer(LLRenderTarget& target); + void shareDepthBuffer(LLRenderTarget& target); //free any allocated resources //safe to call redundantly - virtual void release(); + void release(); //bind target for rendering //applies appropriate viewport - virtual void bindTarget(); + void bindTarget(); //unbind target for rendering static void unbindTarget(); diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index bdc103b917..986c1f2774 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -206,21 +206,40 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) if (features->hasLighting) { - if (features->hasWaterFog) { if (features->disableTextureIndex) { - if (!shader->attachObject("lighting/lightWaterNonIndexedF.glsl")) + if (features->hasAlphaMask) { - return FALSE; + if (!shader->attachObject("lighting/lightWaterAlphaMaskNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightWaterNonIndexedF.glsl")) + { + return FALSE; + } } } else { - if (!shader->attachObject("lighting/lightWaterF.glsl")) + if (features->hasAlphaMask) { - return FALSE; + if (!shader->attachObject("lighting/lightWaterAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightWaterF.glsl")) + { + return FALSE; + } } shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } @@ -230,16 +249,36 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) { if (features->disableTextureIndex) { - if (!shader->attachObject("lighting/lightNonIndexedF.glsl")) + if (features->hasAlphaMask) { - return FALSE; + if (!shader->attachObject("lighting/lightAlphaMaskNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightNonIndexedF.glsl")) + { + return FALSE; + } } } else { - if (!shader->attachObject("lighting/lightF.glsl")) + if (features->hasAlphaMask) { - return FALSE; + if (!shader->attachObject("lighting/lightAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightF.glsl")) + { + return FALSE; + } } shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } @@ -272,14 +311,28 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) { if (features->disableTextureIndex) { - if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedF.glsl")) + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl")) + { + return FALSE; + } + } + else if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedF.glsl")) { return FALSE; } } else { - if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl")) + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightFullbrightWaterAlphaMaskF.glsl")) + { + return FALSE; + } + } + else if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl")) { return FALSE; } @@ -310,16 +363,37 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) { if (features->disableTextureIndex) { - if (!shader->attachObject("lighting/lightFullbrightNonIndexedF.glsl")) + + if (features->hasAlphaMask) { - return FALSE; + if (!shader->attachObject("lighting/lightFullbrightNonIndexedAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightFullbrightNonIndexedF.glsl")) + { + return FALSE; + } } } else { - if (!shader->attachObject("lighting/lightFullbrightF.glsl")) + if (features->hasAlphaMask) { - return FALSE; + if (!shader->attachObject("lighting/lightFullbrightAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightFullbrightF.glsl")) + { + return FALSE; + } } shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } @@ -406,7 +480,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns) LL_DEBUGS("ShaderLoading") << log << LL_ENDL; } } -} + } GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels) { @@ -462,7 +536,11 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade GLcharARB* text[1024]; GLuint count = 0; - if (gGLManager.mGLVersion < 3.f) + if (gGLManager.mGLVersion < 2.1f) + { + text[count++] = strdup("#version 110\n"); + } + else if (gGLManager.mGLVersion < 3.f) { //set version to 1.20 text[count++] = strdup("#version 120\n"); @@ -524,7 +602,12 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade text[count++] = strdup("{\n"); - if (gGLManager.mGLVersion >= 3.f) + if (texture_index_channels == 1) + { //don't use flow control, that's silly + text[count++] = strdup("return texture2D(tex0, texcoord);\n"); + text[count++] = strdup("}\n"); + } + else if (gGLManager.mGLVersion >= 3.f) { text[count++] = strdup("\tswitch (int(vary_texture_index+0.25))\n"); text[count++] = strdup("\t{\n"); @@ -537,6 +620,8 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade } text[count++] = strdup("\t}\n"); + text[count++] = strdup("\treturn vec4(0,0,0,0);\n"); + text[count++] = strdup("}\n"); } else { @@ -557,10 +642,10 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade 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(0,0,0,0);\n"); - text[count++] = strdup("}\n"); + text[count++] = strdup("\treturn vec4(0,0,0,0);\n"); + text[count++] = strdup("}\n"); + } } //copy file into memory @@ -605,11 +690,6 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade } } - //free memory - for (GLuint i = 0; i < count; i++) - { - free(text[i]); - } if (error == GL_NO_ERROR) { //check for errors @@ -623,6 +703,16 @@ 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); + + std::stringstream ostr; + //dump shader source for debugging + for (GLuint i = 0; i < count; i++) + { + ostr << i << ": " << text[i]; + } + + LL_WARNS("ShaderLoading") << "\n" << ostr.str() << llendl; + ret = 0; } } @@ -633,6 +723,12 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade } stop_glerror(); + //free memory + for (GLuint i = 0; i < count; i++) + { + free(text[i]); + } + //successfully loaded, save results if (ret) { diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 4a0b964e61..8fd1193780 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -25,7 +25,6 @@ */ #include "linden_common.h" -#include "llmemory.h" #include <boost/static_assert.hpp> #include "llsys.h" @@ -35,6 +34,9 @@ #include "llmemtype.h" #include "llrender.h" #include "llvector4a.h" +#include "llglslshader.h" +#include "llmemory.h" + //============================================================================ @@ -44,6 +46,7 @@ LLVBOPool LLVertexBuffer::sDynamicVBOPool; LLVBOPool LLVertexBuffer::sStreamIBOPool; LLVBOPool LLVertexBuffer::sDynamicIBOPool; +LLPrivateMemoryPool* LLVertexBuffer::sPrivatePoolp = NULL ; U32 LLVertexBuffer::sBindCount = 0; U32 LLVertexBuffer::sSetCount = 0; S32 LLVertexBuffer::sCount = 0; @@ -65,6 +68,60 @@ S32 LLVertexBuffer::sWeight4Loc = -1; std::vector<U32> LLVertexBuffer::sDeleteList; +const U32 FENCE_WAIT_TIME_NANOSECONDS = 10000; //1 ms + +class LLGLSyncFence : public LLGLFence +{ +public: +#ifdef GL_ARB_sync + GLsync mSync; +#endif + + LLGLSyncFence() + { +#ifdef GL_ARB_sync + mSync = 0; +#endif + } + + ~LLGLSyncFence() + { +#ifdef GL_ARB_sync + if (mSync) + { + glDeleteSync(mSync); + } +#endif + } + + void placeFence() + { +#ifdef GL_ARB_sync + if (mSync) + { + glDeleteSync(mSync); + } + mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); +#endif + } + + void wait() + { +#ifdef GL_ARB_sync + if (mSync) + { + while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED) + { //track the number of times we've waited here + static S32 waits = 0; + waits++; + } + } +#endif + } + + +}; + S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] = { sizeof(LLVector4), // TYPE_VERTEX, @@ -240,7 +297,8 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm) { U32 count = pos.size(); - llassert(norm.size() >= pos.size()); + llassert_always(norm.size() >= pos.size()); + llassert_always(count > 0) ; unbind(); @@ -309,6 +367,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, idx); stop_glerror(); + placeFence(); } void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const @@ -340,6 +399,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT, ((U16*) getIndicesPointer()) + indices_offset); stop_glerror(); + placeFence(); } void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const @@ -365,6 +425,7 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const stop_glerror(); glDrawArrays(sGLMode[mode], first, count); stop_glerror(); + placeFence(); } //static @@ -383,6 +444,11 @@ void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping) } sDisableVBOMapping = sEnableVBOs && no_vbo_mapping ; + + if(!sPrivatePoolp) + { + sPrivatePoolp = LLPrivateMemoryPoolManager::getInstance()->newPool(LLPrivateMemoryPool::STATIC) ; + } } //static @@ -412,7 +478,11 @@ void LLVertexBuffer::cleanupClass() unbind(); clientCopy(); // deletes GL buffers - //llassert_always(!sCount) ; + if(sPrivatePoolp) + { + LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp) ; + sPrivatePoolp = NULL ; + } } void LLVertexBuffer::clientCopy(F64 max_time) @@ -444,9 +514,11 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : mFilthy(FALSE), mEmpty(TRUE), mResized(FALSE), - mDynamicSize(FALSE) + mDynamicSize(FALSE), + mFence(NULL) { LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR); + mFence = NULL; if (!sEnableVBOs) { mUsage = 0 ; @@ -527,9 +599,40 @@ LLVertexBuffer::~LLVertexBuffer() destroyGLIndices(); sCount--; + if (mFence) + { + delete mFence; + } + + mFence = NULL; + llassert_always(!mMappedData && !mMappedIndexData) ; }; +void LLVertexBuffer::placeFence() const +{ + /*if (!mFence && useVBOs()) + { + if (gGLManager.mHasSync) + { + mFence = new LLGLSyncFence(); + } + } + + if (mFence) + { + mFence->placeFence(); + }*/ +} + +void LLVertexBuffer::waitFence() const +{ + /*if (mFence) + { + mFence->wait(); + }*/ +} + //---------------------------------------------------------------------------- void LLVertexBuffer::genBuffer() @@ -629,7 +732,7 @@ void LLVertexBuffer::createGLBuffer() { static int gl_buffer_idx = 0; mGLBuffer = ++gl_buffer_idx; - mMappedData = (U8*) ll_aligned_malloc_16(size); + mMappedData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size); } } @@ -663,7 +766,7 @@ void LLVertexBuffer::createGLIndices() } else { - mMappedIndexData = (U8*) ll_aligned_malloc_16(size); + mMappedIndexData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size); static int gl_buffer_idx = 0; mGLIndices = ++gl_buffer_idx; } @@ -686,7 +789,7 @@ void LLVertexBuffer::destroyGLBuffer() } else { - ll_aligned_free_16(mMappedData); + FREE_MEM(sPrivatePoolp, mMappedData) ; mMappedData = NULL; mEmpty = TRUE; } @@ -715,7 +818,7 @@ void LLVertexBuffer::destroyGLIndices() } else { - ll_aligned_free_16(mMappedIndexData); + FREE_MEM(sPrivatePoolp, mMappedIndexData) ; mMappedIndexData = NULL; mEmpty = TRUE; } @@ -848,8 +951,8 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) { if (!useVBOs()) { - ll_aligned_free_16(mMappedData); - mMappedData = (U8*) ll_aligned_malloc_16(newsize); + FREE_MEM(sPrivatePoolp, mMappedData); + mMappedData = (U8*)ALLOCATE_MEM(sPrivatePoolp, newsize); } mResized = TRUE; } @@ -869,8 +972,8 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) { if (!useVBOs()) { - ll_aligned_free_16(mMappedIndexData); - mMappedIndexData = (U8*) ll_aligned_malloc_16(new_index_size); + FREE_MEM(sPrivatePoolp, mMappedIndexData) ; + mMappedIndexData = (U8*)ALLOCATE_MEM(sPrivatePoolp, new_index_size); } mResized = TRUE; } @@ -892,17 +995,11 @@ BOOL LLVertexBuffer::useVBOs() const { //it's generally ineffective to use VBO for things that are streaming on apple -#if LL_DARWIN - if (!mUsage || mUsage == GL_STREAM_DRAW_ARB) - { - return FALSE; - } -#else if (!mUsage) { return FALSE; } -#endif + return TRUE; } @@ -911,8 +1008,8 @@ void LLVertexBuffer::freeClientBuffer() { if(useVBOs() && sDisableVBOMapping && (mMappedData || mMappedIndexData)) { - ll_aligned_free_16(mMappedData) ; - ll_aligned_free_16(mMappedIndexData) ; + FREE_MEM(sPrivatePoolp, mMappedData) ; + FREE_MEM(sPrivatePoolp, mMappedIndexData) ; mMappedData = NULL ; mMappedIndexData = NULL ; } @@ -922,7 +1019,7 @@ void LLVertexBuffer::allocateClientVertexBuffer() { if(!mMappedData) { - mMappedData = (U8*)ll_aligned_malloc_16(getSize()); + mMappedData = (U8*)ALLOCATE_MEM(sPrivatePoolp, getSize()); } } @@ -930,7 +1027,7 @@ void LLVertexBuffer::allocateClientIndexBuffer() { if(!mMappedIndexData) { - mMappedIndexData = (U8*)ll_aligned_malloc_16(getIndicesSize()); + mMappedIndexData = (U8*)ALLOCATE_MEM(sPrivatePoolp, getIndicesSize()); } } @@ -967,8 +1064,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran if (useVBOs()) { - - if (sDisableVBOMapping || gGLManager.mHasMapBufferRange) + if (sDisableVBOMapping || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange) { if (count == -1) { @@ -1008,6 +1104,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES); setBuffer(0, type); mVertexLocked = TRUE; + sMappedCount++; stop_glerror(); if(sDisableVBOMapping) @@ -1018,29 +1115,50 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran else { U8* src = NULL; -#ifdef GL_ARB_map_buffer_range + waitFence(); if (gGLManager.mHasMapBufferRange) { if (map_range) { +#ifdef GL_ARB_map_buffer_range S32 offset = mOffsets[type] + sTypeSize[type]*index; S32 length = (sTypeSize[type]*count+0xF) & ~0xF; - src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_INVALIDATE_RANGE_BIT); + src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length, + GL_MAP_WRITE_BIT | + GL_MAP_FLUSH_EXPLICIT_BIT | + GL_MAP_INVALIDATE_RANGE_BIT); +#endif } else { - src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); +#ifdef GL_ARB_map_buffer_range + src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize, + GL_MAP_WRITE_BIT | + GL_MAP_FLUSH_EXPLICIT_BIT); +#endif + } + } + else if (gGLManager.mHasFlushBufferRange) + { + if (map_range) + { + glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE); + glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE); + src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + } + else + { + src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); } } else -#else - llassert_always(!gGLManager.mHasMapBufferRange); -#endif { map_range = false; src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); } + llassert(src != NULL); + mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src); mAlignedOffset = mMappedData - src; @@ -1051,12 +1169,9 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran { log_glerror(); - //check the availability of memory - U32 avail_phy_mem, avail_vir_mem; - LLMemoryInfo::getAvailableMemoryKB(avail_phy_mem, avail_vir_mem) ; - llinfos << "Available physical mwmory(KB): " << avail_phy_mem << llendl ; - llinfos << "Available virtual memory(KB): " << avail_vir_mem << llendl; - + //check the availability of memory + LLMemory::logMemoryInfo(TRUE) ; + if(!sDisableVBOMapping) { //-------------------- @@ -1082,7 +1197,6 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran llerrs << "memory allocation for vertex data failed." << llendl ; } } - sMappedCount++; } } else @@ -1090,7 +1204,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran map_range = false; } - if (map_range && !sDisableVBOMapping) + if (map_range && gGLManager.mHasMapBufferRange && !sDisableVBOMapping) { return mMappedData; } @@ -1114,7 +1228,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) if (useVBOs()) { - if (sDisableVBOMapping || gGLManager.mHasMapBufferRange) + if (sDisableVBOMapping || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange) { if (count == -1) { @@ -1152,6 +1266,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) setBuffer(0, TYPE_INDEX); mIndexLocked = TRUE; + sMappedCount++; stop_glerror(); if(sDisableVBOMapping) @@ -1162,29 +1277,51 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) else { U8* src = NULL; -#ifdef GL_ARB_map_buffer_range + waitFence(); if (gGLManager.mHasMapBufferRange) { if (map_range) { +#ifdef GL_ARB_map_buffer_range S32 offset = sizeof(U16)*index; S32 length = sizeof(U16)*count; - src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_INVALIDATE_RANGE_BIT); + src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, + GL_MAP_WRITE_BIT | + GL_MAP_FLUSH_EXPLICIT_BIT | + GL_MAP_INVALIDATE_RANGE_BIT); +#endif + } + else + { +#ifdef GL_ARB_map_buffer_range + src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices, + GL_MAP_WRITE_BIT | + GL_MAP_FLUSH_EXPLICIT_BIT); +#endif + } + } + else if (gGLManager.mHasFlushBufferRange) + { + if (map_range) + { + glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE); + glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE); + src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); } else { - src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); + src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); } } else -#else - llassert_always(!gGLManager.mHasMapBufferRange); -#endif { map_range = false; src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); } + llassert(src != NULL); + + mMappedIndexData = src; //LL_NEXT_ALIGNED_ADDRESS<U8>(src); mAlignedIndexOffset = mMappedIndexData - src; stop_glerror(); @@ -1194,6 +1331,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) if (!mMappedIndexData) { log_glerror(); + LLMemory::logMemoryInfo(TRUE) ; if(!sDisableVBOMapping) { @@ -1211,15 +1349,13 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) llerrs << "memory allocation for Index data failed. " << llendl ; } } - - sMappedCount++; } else { map_range = false; } - if (map_range && !sDisableVBOMapping) + if (map_range && gGLManager.mHasMapBufferRange && !sDisableVBOMapping) { return mMappedIndexData; } @@ -1268,8 +1404,7 @@ void LLVertexBuffer::unmapBuffer(S32 type) } else { -#ifdef GL_ARB_map_buffer_range - if (gGLManager.mHasMapBufferRange) + if (gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange) { if (!mMappedVertexRegions.empty()) { @@ -1279,16 +1414,22 @@ void LLVertexBuffer::unmapBuffer(S32 type) const MappedRegion& region = mMappedVertexRegions[i]; S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0; S32 length = sTypeSize[region.mType]*region.mCount; - glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length); + if (gGLManager.mHasMapBufferRange) + { +#ifdef GL_ARB_map_buffer_range + glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length); +#endif + } + else if (gGLManager.mHasFlushBufferRange) + { + glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER_ARB, offset, length); + } stop_glerror(); } mMappedVertexRegions.clear(); } } -#else - llassert_always(!gGLManager.mHasMapBufferRange); -#endif stop_glerror(); glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); stop_glerror(); @@ -1326,8 +1467,7 @@ void LLVertexBuffer::unmapBuffer(S32 type) } else { -#ifdef GL_ARB_map_buffer_range - if (gGLManager.mHasMapBufferRange) + if (gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange) { if (!mMappedIndexRegions.empty()) { @@ -1336,16 +1476,24 @@ void LLVertexBuffer::unmapBuffer(S32 type) const MappedRegion& region = mMappedIndexRegions[i]; S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0; S32 length = sizeof(U16)*region.mCount; - glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length); + if (gGLManager.mHasMapBufferRange) + { +#ifdef GL_ARB_map_buffer_range + glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length); +#endif + } + else if (gGLManager.mHasFlushBufferRange) + { +#ifdef GL_APPLE_flush_buffer_range + glFlushMappedBufferRangeAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length); +#endif + } stop_glerror(); } mMappedIndexRegions.clear(); } } -#else - llassert_always(!gGLManager.mHasMapBufferRange); -#endif stop_glerror(); glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); stop_glerror(); diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index aa5df305a6..578cec3885 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -70,10 +70,16 @@ protected: } }; +class LLGLFence +{ +public: + virtual void placeFence() = 0; + virtual void wait() = 0; +}; //============================================================================ // base class - +class LLPrivateMemoryPool ; class LLVertexBuffer : public LLRefCount { public: @@ -270,6 +276,15 @@ protected: std::vector<MappedRegion> mMappedVertexRegions; std::vector<MappedRegion> mMappedIndexRegions; + mutable LLGLFence* mFence; + + void placeFence() const; + void waitFence() const; + + +private: + static LLPrivateMemoryPool* sPrivatePoolp ; + public: static S32 sCount; static S32 sGLCount; |