From 7f0c81918575d3f05e4eadc160b600eaa8b383d1 Mon Sep 17 00:00:00 2001 From: mobserveur Date: Sat, 30 Aug 2025 01:59:43 +0200 Subject: Performance Optimisations, Bloom effect, Visuals Panel This commit contains performance optimisations in the the pipeline, framebuffer, vertexbuffer, reflection probes, shadows. It also fixes many opengl errors, modifies the opengl debugging, and adds a visuals effects panel. --- indra/llrender/llcubemaparray.cpp | 3 + indra/llrender/llgl.cpp | 14 +-- indra/llrender/llgl.h | 13 ++- indra/llrender/llimagegl.cpp | 7 +- indra/llrender/llrender.cpp | 117 +++++++++++++--------- indra/llrender/llrender.h | 4 +- indra/llrender/llrender2dutils.cpp | 5 +- indra/llrender/llrendertarget.cpp | 197 ++++++++++++++++++++++++++++++------- indra/llrender/llrendertarget.h | 15 ++- indra/llrender/llshadermgr.cpp | 20 +++- indra/llrender/llshadermgr.h | 12 +++ indra/llrender/llvertexbuffer.cpp | 171 ++++++++++++++++++++------------ 12 files changed, 405 insertions(+), 173 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp index fb35e002df..e0a8782c33 100644 --- a/indra/llrender/llcubemaparray.cpp +++ b/indra/llrender/llcubemaparray.cpp @@ -114,6 +114,8 @@ LLCubeMapArray::LLCubeMapArray(LLCubeMapArray& lhs, U32 width, U32 count) : mTex allocate(mWidth, lhs.mImage->getComponents(), count, lhs.mImage->getUseMipMaps(), lhs.mHDR); // Copy each cubemap from the incoming array to the new array + // The call to glTexSubImage3D causes an INVALID OPERATION OpenGL error. For now we comment this.. + /* U32 min_count = std::min(count, lhs.mCount); for (U32 i = 0; i < min_count * 6; ++i) { @@ -133,6 +135,7 @@ LLCubeMapArray::LLCubeMapArray(LLCubeMapArray& lhs, U32 width, U32 count) : mTex glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, i, mWidth, mWidth, 1, components, GL_UNSIGNED_BYTE, scaled_image->getData()); } } + */ } LLCubeMapArray::~LLCubeMapArray() diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index ac66faaf5a..cc619e2086 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -2279,26 +2279,28 @@ void rotate_quat(LLQuaternion& rotation) void flush_glerror() { + if(!gDebugGL) return; glGetError(); } -//this function outputs gl error to the log file, does not crash the code. -void log_glerror() +void log_glerror(std::string comment) { + if(!gDebugGL) return; + if (LL_UNLIKELY(!gGLManager.mInited)) { return ; } - // Create or update texture to be used with this data + GLenum error; error = glGetError(); - while (LL_UNLIKELY(error)) + if (error != GL_NO_ERROR) { #if GLU_VERSION_1_1 GLubyte const * gl_error_msg = gluErrorString(error); if (NULL != gl_error_msg) { - LL_WARNS() << "GL Error: " << error << " GL Error String: " << gl_error_msg << LL_ENDL ; + LL_WARNS() << "GL Error (" << comment << ")" << error << ": " << gl_error_msg << LL_ENDL; } else #endif // GLU_VERSION_1_1 @@ -2307,7 +2309,6 @@ void log_glerror() // you'll probably have to grep for the number in glext.h. LL_WARNS() << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << LL_ENDL; } - error = glGetError(); } } @@ -2385,6 +2386,7 @@ void assert_glerror() void clear_glerror() { + if(!gDebugGL) return; glGetError(); glGetError(); } diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index bf8368a7b3..130b06f9df 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -154,17 +154,20 @@ void rotate_quat(LLQuaternion& rotation); void flush_glerror(); // Flush GL errors when we know we're handling them correctly. -void log_glerror(); +void log_glerror(std::string comment); void assert_glerror(); void clear_glerror(); -#if !LL_RELEASE_FOR_DOWNLOAD -# define stop_glerror() assert_glerror() -# define llglassertok() assert_glerror() -# define STOP_GLERROR stop_glerror() +//#if !LL_RELEASE_FOR_DOWNLOAD +#if 1 +# define LOG_GLERROR(COMMENT) log_glerror(COMMENT) +# define stop_glerror() log_glerror("stop") +# define llglassertok() log_glerror("ASSERTOK") +# define STOP_GLERROR log_glerror("STOP") #else +# define LOG_GLERROR(COMMENT) # define stop_glerror() # define llglassertok() # define STOP_GLERROR diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 558c3b062a..42af68c276 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -358,6 +358,7 @@ S32 LLImageGL::dataFormatBits(S32 dataformat) #endif case GL_DEPTH_COMPONENT: return 24; case GL_DEPTH_COMPONENT24: return 24; + case GL_RGBA16: return 64; case GL_R16F: return 16; case GL_RG16F: return 32; case GL_RGB16F: return 48; @@ -1290,7 +1291,7 @@ bool LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_ { glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height); mGLTextureCreated = true; - stop_glerror(); + LOG_GLERROR("LLImageGL::setSubImageFromFrameBuffer()"); return true; } else @@ -2583,6 +2584,8 @@ bool LLImageGL::scaleDown(S32 desired_discard) return false; } + //LL_WARNS() << "scaleDown" << LL_ENDL; + S32 mip = desired_discard - mCurrentDiscardLevel; S32 desired_width = getWidth(desired_discard); @@ -2600,6 +2603,7 @@ bool LLImageGL::scaleDown(S32 desired_discard) free_tex_image(mTexName); glTexImage2D(mTarget, 0, mFormatInternal, desired_width, desired_height, 0, mFormatPrimary, mFormatType, nullptr); glCopyTexSubImage2D(mTarget, 0, 0, 0, 0, 0, desired_width, desired_height); + LOG_GLERROR("LLImageGL::scaleDown() - glCopyTexSubImage2D"); alloc_tex_image(desired_width, desired_height, mFormatInternal, 1); mTexOptionsDirty = true; @@ -2609,6 +2613,7 @@ bool LLImageGL::scaleDown(S32 desired_discard) LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glGenerateMipmap"); gGL.getTexUnit(0)->bind(this); glGenerateMipmap(mTarget); + LOG_GLERROR("LLImageGL::scaleDown() - glGenerateMipmap"); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } } diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index cbb178b6f8..d0e268f08c 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1,4 +1,4 @@ - /** +/** * @file llrender.cpp * @brief LLRender implementation * @@ -139,21 +139,21 @@ U32 LLTexUnit::getInternalType(eTextureType type) void LLTexUnit::refreshState(void) { - // We set dirty to true so that the tex unit knows to ignore caching - // and we reset the cached tex unit state +// We set dirty to true so that the tex unit knows to ignore caching +// and we reset the cached tex unit state - gGL.flush(); +gGL.flush(); - glActiveTexture(GL_TEXTURE0 + mIndex); +glActiveTexture(GL_TEXTURE0 + mIndex); - if (mCurrTexType != TT_NONE) - { - glBindTexture(sGLTextureType[mCurrTexType], mCurrTexture); - } - else - { - glBindTexture(GL_TEXTURE_2D, 0); - } +if (mCurrTexType != TT_NONE) +{ + glBindTexture(sGLTextureType[mCurrTexType], mCurrTexture); +} +else +{ + glBindTexture(GL_TEXTURE_2D, 0); +} } void LLTexUnit::activate(void) @@ -203,6 +203,7 @@ void LLTexUnit::bindFast(LLTexture* texture) glActiveTexture(GL_TEXTURE0 + mIndex); gGL.mCurrTextureUnitIndex = mIndex; mCurrTexture = gl_tex->getTexName(); + mCurrTexType = gl_tex->getTarget(); if (!mCurrTexture) { LL_PROFILE_ZONE_NAMED("MISSING TEXTURE"); @@ -479,41 +480,49 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio { if (mIndex < 0 || mCurrTexture == 0 || mCurrTexType == LLTexUnit::TT_MULTISAMPLE_TEXTURE) return; + GLenum target = sGLTextureType[mCurrTexType]; + + if (mCurrTexType == LLTexUnit::TT_NONE) + { + LL_WARNS() << "setTextureFilteringOption() Error: mCurrTexType==TT_NONE texture: " << mCurrTexture << LL_ENDL; + gGL.debugTexUnits(); + } + gGL.flush(); if (option == TFO_POINT) { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } else { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } if (option >= TFO_TRILINEAR && mHasMipMaps) { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } else if (option >= TFO_BILINEAR) { if (mHasMipMaps) { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); } else { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } } else { if (mHasMipMaps) { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); } else { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } } @@ -521,11 +530,11 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio { if (LLImageGL::sGlobalUseAnisotropic && option == TFO_ANISOTROPIC) { - glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, gGLManager.mMaxAnisotropy); + glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, gGLManager.mMaxAnisotropy); } else { - glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); + glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); } } } @@ -651,12 +660,12 @@ void LLTexUnit::debugTextureUnit(void) LLLightState::LLLightState(S32 index) : mIndex(index), - mEnabled(false), - mConstantAtten(1.f), - mLinearAtten(0.f), - mQuadraticAtten(0.f), - mSpotExponent(0.f), - mSpotCutoff(180.f) +mEnabled(false), +mConstantAtten(1.f), +mLinearAtten(0.f), +mQuadraticAtten(0.f), +mSpotExponent(0.f), +mSpotCutoff(180.f) { if (mIndex == 0) { @@ -815,7 +824,7 @@ void LLLightState::setSpotDirection(const LLVector3& direction) } LLRender::LLRender() - : mDirty(false), +: mDirty(false), mCount(0), mMode(LLRender::TRIANGLES), mCurrTextureUnitIndex(0) @@ -908,13 +917,12 @@ bool LLRender::init(bool needs_vertex_buffer) void LLRender::initVertexBuffer() { llassert_always(mBuffer.isNull()); - stop_glerror(); mBuffer = new LLVertexBuffer(immediate_mask); - mBuffer->allocateBuffer(4096, 0); + mBuffer->allocateBuffer(16384, 0); mBuffer->getVertexStrider(mVerticesp); mBuffer->getTexCoord0Strider(mTexcoordsp); mBuffer->getColorStrider(mColorsp); - stop_glerror(); + LOG_GLERROR("LLRender::initVertexBuffer()"); } void LLRender::resetVertexBuffer() @@ -1000,7 +1008,6 @@ void LLRender::syncLightState() void LLRender::syncMatrices() { - STOP_GLERROR; LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; static const U32 name[] = @@ -1145,7 +1152,7 @@ void LLRender::syncMatrices() syncLightState(); } } - STOP_GLERROR; + LOG_GLERROR("LLRender::syncMatrices()"); } void LLRender::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z) @@ -1448,7 +1455,7 @@ void LLRender::blendFunc(eBlendFactor sfactor, eBlendFactor dfactor) } void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor, - eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor) + eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor) { llassert(color_sfactor < BF_UNDEF); llassert(color_dfactor < BF_UNDEF); @@ -1465,7 +1472,7 @@ void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor, flush(); glBlendFuncSeparate(sGLBlendFactor[color_sfactor], sGLBlendFactor[color_dfactor], - sGLBlendFactor[alpha_sfactor], sGLBlendFactor[alpha_dfactor]); + sGLBlendFactor[alpha_sfactor], sGLBlendFactor[alpha_dfactor]); } } @@ -1555,7 +1562,7 @@ void LLRender::begin(const GLuint& mode) mMode == LLRender::TRIANGLES || mMode == LLRender::POINTS) { - flush(); + flush("LLRender::begin"); } else if (mCount != 0) { @@ -1566,7 +1573,7 @@ void LLRender::begin(const GLuint& mode) } } -void LLRender::end() +void LLRender::end(std::string comment_) { if (mCount == 0) { @@ -1579,13 +1586,13 @@ void LLRender::end() mMode != LLRender::POINTS) || mCount > 2048) { - flush(); + flush("from end " + comment_); } } -void LLRender::flush() +void LLRender::flush(std::string comment_) { - STOP_GLERROR; + LOG_GLERROR("LLRender::flush() begin " + comment_); if (mCount > 0) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; @@ -1604,8 +1611,8 @@ void LLRender::flush() { if (mCount%3 != 0) { - count -= (mCount % 3); - LL_WARNS() << "Incomplete triangle requested." << LL_ENDL; + count -= (mCount % 3); + LL_WARNS() << "Incomplete triangle requested." << LL_ENDL; } } @@ -1655,6 +1662,8 @@ void LLRender::flush() resetStriders(count); } + + LOG_GLERROR("LLRender::flush() end " + comment_); } LLVertexBuffer* LLRender::bufferfromCache(U32 attribute_mask, U32 count) @@ -2026,7 +2035,8 @@ void LLRender::debugTexUnits(void) std::string active_enabled = "false"; for (U32 i = 0; i < mTexUnits.size(); i++) { - if (getTexUnit(i)->mCurrTexType != LLTexUnit::TT_NONE) + //if (getTexUnit(i)->mCurrTexType != LLTexUnit::TT_NONE) + if(1) { if (i == mCurrTextureUnitIndex) active_enabled = "true"; LL_INFOS("TextureUnit") << "TexUnit: " << i << " Enabled" << LL_ENDL; @@ -2044,8 +2054,19 @@ void LLRender::debugTexUnits(void) case LLTexUnit::TT_CUBE_MAP: LL_CONT << "Cube Map"; break; + case LLTexUnit::TT_CUBE_MAP_ARRAY: + LL_CONT << "Cube Map Array"; + break; + + case LLTexUnit::TT_MULTISAMPLE_TEXTURE: + LL_CONT << "Multisample Texture"; + break; + + case LLTexUnit::TT_TEXTURE_3D: + LL_CONT << "Texture 3D"; + break; default: - LL_CONT << "ARGH!!! NONE!"; + LL_CONT << "ARGH!!! NONE! -> type = " << getTexUnit(i)->mCurrTexType; break; } LL_CONT << ", Texture Bound: " << getTexUnit(i)->mCurrTexture << LL_ENDL; @@ -2108,9 +2129,9 @@ glm::vec3 mul_mat4_vec3(const glm::mat4& mat, const glm::vec3& vec) #if 1 // SIMD path results in strange crashes. Fall back to scalar for now. const float w = vec[0] * mat[0][3] + vec[1] * mat[1][3] + vec[2] * mat[2][3] + mat[3][3]; return glm::vec3( - (vec[0] * mat[0][0] + vec[1] * mat[1][0] + vec[2] * mat[2][0] + mat[3][0]) / w, - (vec[0] * mat[0][1] + vec[1] * mat[1][1] + vec[2] * mat[2][1] + mat[3][1]) / w, - (vec[0] * mat[0][2] + vec[1] * mat[1][2] + vec[2] * mat[2][2] + mat[3][2]) / w + (vec[0] * mat[0][0] + vec[1] * mat[1][0] + vec[2] * mat[2][0] + mat[3][0]) / w, + (vec[0] * mat[0][1] + vec[1] * mat[1][1] + vec[2] * mat[2][1] + mat[3][1]) / w, + (vec[0] * mat[0][2] + vec[1] * mat[1][2] + vec[2] * mat[2][2] + mat[3][2]) / w ); #else LLVector4a x, y, z, s, t, p, q; diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 97c47bcae9..f0f9cd4364 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -421,14 +421,14 @@ public: LLVector3 getUITranslation(); LLVector3 getUIScale(); - void flush(); + void flush(std::string comment_ = ""); // if list is set, will store buffers in list for later use, if list isn't set, will use cache void beginList(std::list *list); void endList(); void begin(const GLuint& mode); - void end(); + void end(std::string comment_ = ""); U8 getMode() const { return mMode; } diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index 9144ce6d62..0ee47dec6d 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -833,8 +833,7 @@ void gl_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& c { gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], color.mV[VALPHA]); - gGL.flush(); - glLineWidth(2.5f); + LLRender2D::setLineWidth(2.5f); gGL.begin(LLRender::LINES); { @@ -1802,12 +1801,10 @@ void LLRender2D::setLineWidth(F32 width) // If outside the allowed range, glLineWidth fails with "invalid value". // On Darwin, the range is [1, 1]. static GLfloat range[2]{0.0}; -#if GL_VERSION_1_2 if (range[1] == 0) { glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, range); } -#endif width *= lerp(LLRender::sUIGLScaleFactor.mV[VX], LLRender::sUIGLScaleFactor.mV[VY], 0.5f); glLineWidth(llclamp(width, range[0], range[1])); } diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 0e4aa2ee7a..957c85b606 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -158,6 +158,8 @@ void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name) llassert(mTex.empty()); // mTex must be empty with this mode (binding target should be done via LLImageGL) llassert(!isBoundInStack()); + U32 target = getTarget(); + if (mFBO == 0) { glGenFramebuffers(1, (GLuint*)&mFBO); @@ -174,14 +176,14 @@ void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name) mTex.push_back(use_name); - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + glBindFramebuffer(target, mFBO); + glFramebufferTexture2D(target, GL_COLOR_ATTACHMENT0, LLTexUnit::getInternalType(mUsage), use_name, 0); stop_glerror(); check_framebuffer_status(); - glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); + glBindFramebuffer(target, sCurFBO); } void LLRenderTarget::releaseColorAttachment() @@ -194,6 +196,7 @@ void LLRenderTarget::releaseColorAttachment() glBindFramebuffer(GL_FRAMEBUFFER, mFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, LLTexUnit::getInternalType(mUsage), 0, 0); glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); + LOG_GLERROR(mName + " releaseColorAttachment()"); mTex.clear(); } @@ -208,6 +211,8 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) return true; } + U32 target = getTarget(); + U32 offset = static_cast(mTex.size()); if( offset >= 4 ) @@ -226,12 +231,76 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) LLImageGL::generateTextures(1, &tex); gGL.getTexUnit(0)->bindManual(mUsage, tex); - stop_glerror(); - + U32 miplevel = mMipLevels; + U32 intformat = color_fmt; + U32 pixformat = GL_RGBA; + U32 pixtype = GL_UNSIGNED_BYTE; { - clear_glerror(); - LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false); + //clear_glerror(); + + if(color_fmt == GL_RGB10_A2) + { + pixformat = GL_RGBA; + pixtype = GL_UNSIGNED_BYTE; + } + else if(color_fmt == GL_R11F_G11F_B10F) + { + pixformat = GL_RGB; + pixtype = GL_HALF_FLOAT; + } + else if(color_fmt == GL_R8) + { + pixformat = GL_RED; + pixtype = GL_UNSIGNED_BYTE; + } + else if(color_fmt == GL_R16F) + { + pixformat = GL_RED; + pixtype = GL_HALF_FLOAT; + } + else if(color_fmt == GL_RG16F) + { + pixformat = GL_RG; + pixtype = GL_HALF_FLOAT; + } + else if(color_fmt == GL_RGBA16F) + { + pixformat = GL_RGBA; + pixtype = GL_HALF_FLOAT; + } + else if(color_fmt == GL_RGB16F) + { + pixformat = GL_RGB; + pixtype = GL_HALF_FLOAT; + } + else if(color_fmt == GL_RGB8) + { + pixformat = GL_RGB; + pixtype = GL_UNSIGNED_BYTE; + } + else if(color_fmt == GL_RGB) + { + pixformat = GL_RGB; + pixtype = GL_UNSIGNED_BYTE; + } + else if(color_fmt == GL_RGBA) + { + pixformat = GL_RGBA; + pixtype = GL_UNSIGNED_BYTE; + } + else if(color_fmt == GL_RGBA8) + { + pixformat = GL_RGBA; + pixtype = GL_UNSIGNED_BYTE; + } + else + { + pixformat = GL_RGBA; + pixtype = GL_UNSIGNED_BYTE; + } + + LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, pixformat, pixtype, NULL, false); if (glGetError() != GL_NO_ERROR) { LL_WARNS() << "Could not allocate color buffer for render target." << LL_ENDL; @@ -241,32 +310,30 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) sBytesAllocated += mResX*mResY*4; - stop_glerror(); - - if (offset == 0) { //use bilinear filtering on single texture render targets that aren't multisampled gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - stop_glerror(); + LOG_GLERROR(mName + " setting filtering to TFO_BILINEAR"); } else { //don't filter data attachments gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - stop_glerror(); + LOG_GLERROR(mName + " setting filtering to TFO_POINT"); } #if GL_VERSION_3_1 if (mUsage != LLTexUnit::TT_RECT_TEXTURE) { gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); - stop_glerror(); + LOG_GLERROR(mName + " setting address mode to TAM_MIRROR"); + } else #endif { // ATI doesn't support mirrored repeat for rectangular textures. gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - stop_glerror(); + LOG_GLERROR(mName + " setting address mode to TAM_CLAMP"); } if (mFBO) @@ -285,7 +352,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) if (gDebugGL) { //bind and unbind to validate target - bindTarget(); + bindTarget(mName, mMode); flush(); } @@ -300,16 +367,15 @@ bool LLRenderTarget::allocateDepth() gGL.getTexUnit(0)->bindManual(mUsage, mDepth); 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, false); + + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_FLOAT, NULL, false); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); sBytesAllocated += mResX*mResY*4; if (glGetError() != GL_NO_ERROR) { - LL_WARNS() << "Unable to allocate depth buffer for render target." << LL_ENDL; + LL_WARNS() << "Unable to allocate depth buffer for render target " << mName << LL_ENDL; return false; } @@ -345,6 +411,8 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); + LOG_GLERROR(mName + " shareDepthBuffer()"); + target.mUseDepth = true; } } @@ -408,19 +476,32 @@ void LLRenderTarget::release() LLImageGL::deleteTextures(1, &mTex[0]); } + LOG_GLERROR(mName + " release()"); + mTex.clear(); mInternalFormat.clear(); mResX = mResY = 0; } -void LLRenderTarget::bindTarget() +void LLRenderTarget::bindTarget(std::string name_, U32 mode_) { LL_PROFILE_GPU_ZONE("bindTarget"); llassert(mFBO); llassert(!isBoundInStack()); - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + //mode_ = 0; + + mMode = mode_; + mName = name_; + + U32 target = getTarget(); + + glBindFramebuffer(target, mFBO); + LOG_GLERROR(mName+" bindTarget()"); + + //attach(); + sCurFBO = mFBO; //setup multiple render targets @@ -430,17 +511,34 @@ void LLRenderTarget::bindTarget() GL_COLOR_ATTACHMENT3}; if (mTex.empty()) - { //no color buffer to draw to - GLenum buffers[] = {GL_NONE}; - glDrawBuffers(0, buffers); + { //no color buffer to draw to + if(!mUseDepth) LL_WARNS() << mName << " HAS NO COLOR BUFFER AND NO DEPTH!!" << LL_ENDL; + glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); } - else + else if(mMode == 0) { glDrawBuffers(static_cast(mTex.size()), drawbuffers); glReadBuffer(GL_COLOR_ATTACHMENT0); + + LOG_GLERROR(mName+" read and write buffers"); + + } + else if(mMode == 1) + { + glDrawBuffers(static_cast(mTex.size()), drawbuffers); + glReadBuffer(GL_NONE); + LOG_GLERROR(mName+" draw buffer"); + } + else if(mMode == 2) + { + glDrawBuffer(GL_NONE); + glReadBuffer(GL_COLOR_ATTACHMENT0); + LOG_GLERROR(mName+" read buffer"); } + check_framebuffer_status(); + LOG_GLERROR(mName+" checked status"); glViewport(0, 0, mResX, mResY); sCurResX = mResX; @@ -454,24 +552,22 @@ void LLRenderTarget::clear(U32 mask_in) { LL_PROFILE_GPU_ZONE("clear"); llassert(mFBO); - U32 mask = GL_COLOR_BUFFER_BIT; - if (mUseDepth) - { - mask |= GL_DEPTH_BUFFER_BIT; + U32 mask = 0; + + if(!mTex.empty()) mask |= GL_COLOR_BUFFER_BIT; + if (mUseDepth) mask |= GL_DEPTH_BUFFER_BIT; - } if (mFBO) { check_framebuffer_status(); - stop_glerror(); glClear(mask & mask_in); - stop_glerror(); + LOG_GLERROR(mName + "clear()"); } else { LLGLEnable scissor(GL_SCISSOR_TEST); glScissor(0, 0, mResX, mResY); - stop_glerror(); + LOG_GLERROR(""); glClear(mask & mask_in); } } @@ -514,29 +610,43 @@ void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilt } gGL.getTexUnit(channel)->setTextureFilteringOption(filter_options); + + LOG_GLERROR(mName + " bindTexture()"); } void LLRenderTarget::flush() { LL_PROFILE_GPU_ZONE("rt flush"); + + LOG_GLERROR(mName+" rt flush() A"); + gGL.flush(); llassert(mFBO); llassert(sCurFBO == mFBO); llassert(sBoundTarget == this); - if (mGenerateMipMaps == LLTexUnit::TMG_AUTO) + if (mGenerateMipMaps == LLTexUnit::TMG_AUTO && mMode != 2) { LL_PROFILE_GPU_ZONE("rt generate mipmaps"); - bindTexture(0, 0, LLTexUnit::TFO_TRILINEAR); + //bindTexture(0, 0, LLTexUnit::TFO_TRILINEAR); + bindTexture(0, 0, LLTexUnit::TFO_ANISOTROPIC); glGenerateMipmap(GL_TEXTURE_2D); + LOG_GLERROR(mName + " glGenerateMipmap()"); } + LOG_GLERROR(mName + " rt flush() B"); + + unbind(); +} + +void LLRenderTarget::unbind() +{ if (mPreviousRT) { // a bit hacky -- pop the RT stack back two frames and push // the previous frame back on to play nice with the GL state machine sBoundTarget = mPreviousRT->mPreviousRT; - mPreviousRT->bindTarget(); + mPreviousRT->bindTarget(mPreviousRT->mName, mPreviousRT->mMode); } else { @@ -547,9 +657,10 @@ void LLRenderTarget::flush() sCurResX = gGLViewport[2]; sCurResY = gGLViewport[3]; glReadBuffer(GL_BACK); - GLenum drawbuffers[] = {GL_BACK}; - glDrawBuffers(1, drawbuffers); + glDrawBuffer(GL_BACK); } + + LOG_GLERROR(mName + " rt unbind()"); } bool LLRenderTarget::isComplete() const @@ -604,3 +715,13 @@ void LLRenderTarget::swapFBORefs(LLRenderTarget& other) std::swap(mFBO, other.mFBO); std::swap(mTex, other.mTex); } + +U32 LLRenderTarget::getTarget() +{ + U32 target = GL_FRAMEBUFFER; + + if(mMode == 1) target = GL_DRAW_FRAMEBUFFER; + else if(mMode == 2) target = GL_READ_FRAMEBUFFER; + + return target; +} \ No newline at end of file diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index cd3290cf66..583d0054ac 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -33,9 +33,9 @@ #include "llrender.h" /* - Wrapper around OpenGL framebuffer objects for use in render-to-texture +Wrapper around OpenGL framebuffer objects for use in render-to-texture - SAMPLE USAGE: +SAMPLE USAGE: LLRenderTarget target; @@ -126,7 +126,7 @@ public: // If an LLRenderTarget is currently bound, stores a reference to that LLRenderTarget // and restores previous binding on flush() (maintains a stack of Render Targets) // Asserts that this target is not currently bound in the stack - void bindTarget(); + void bindTarget(std::string name_ = "nd", U32 mode_ = 0); //clear render targer, clears depth buffer if present, //uses scissor rect if in copy-to-texture mode @@ -158,6 +158,7 @@ public: // If an LLRenderTarget was bound when bindTarget was called, binds that RenderTarget for rendering (maintains RT stack) // asserts that this target is currently bound void flush(); + void unbind(); //Returns TRUE if target is ready to be rendered into. //That is, if the target has been allocated with at least @@ -174,11 +175,15 @@ public: static LLRenderTarget* sBoundTarget; + U32 mMode; + std::string mName; + protected: U32 mResX; U32 mResY; std::vector mTex; std::vector mInternalFormat; + std::vector mPixFormat; U32 mFBO; LLRenderTarget* mPreviousRT = nullptr; @@ -188,6 +193,10 @@ protected: U32 mMipLevels; LLTexUnit::eTextureType mUsage; + +private: + U32 getTarget(); + }; #endif diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 4807c12226..3bc71a7413 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -451,7 +451,7 @@ void LLShaderMgr::dumpObjectLog(GLuint ret, bool warns, const std::string& filen LL_SHADER_LOADING_WARNS() << "Shader loading from " << fname << LL_ENDL; LL_SHADER_LOADING_WARNS() << "\n" << log << LL_ENDL; } - } +} GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map* defines, S32 texture_index_channels) { @@ -571,7 +571,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev } else { - shader_code_text[shader_code_count++] = strdup("#version 400\n"); + shader_code_text[shader_code_count++] = strdup("#version 410\n"); } } else if (major_version == 3) @@ -740,7 +740,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev //copy file into memory enum { - flag_write_to_out_of_extra_block_area = 0x01 + flag_write_to_out_of_extra_block_area = 0x01 , flag_extra_block_marker_was_found = 0x02 }; @@ -756,7 +756,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev #endif while(NULL != fgets((char *)buff, 1024, file) - && shader_code_count < (LL_ARRAY_SIZE(shader_code_text) - LL_ARRAY_SIZE(extra_code_text))) + && shader_code_count < (LL_ARRAY_SIZE(shader_code_text) - LL_ARRAY_SIZE(extra_code_text))) { file_lines_count++; @@ -1501,6 +1501,18 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("searchTex"); mReservedUniforms.push_back("blendTex"); + mReservedUniforms.push_back("bloomEMap"); + mReservedUniforms.push_back("bloomBlurredMap"); + mReservedUniforms.push_back("bloomHorizontal"); + mReservedUniforms.push_back("bloomBlurRadius"); + mReservedUniforms.push_back("bloomExtractBrightness"); + mReservedUniforms.push_back("bloomStrength"); + mReservedUniforms.push_back("bloomExtractEmissive"); + mReservedUniforms.push_back("bloomExtractEmissive2"); + mReservedUniforms.push_back("bloomExtractORM"); + mReservedUniforms.push_back("bloomExtractMetal"); + mReservedUniforms.push_back("bloomExtractNonMetal"); + llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS); std::set dupe_check; diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 46788841a5..8b0bfc6bbe 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -341,6 +341,18 @@ public: SMAA_SEARCH_TEX, // "searchTex" SMAA_BLEND_TEX, // "blendTex" + BLOOM_EMAP, // "bloomEMap" + BLOOM_BMAP, // "bloomBlurredMap" + BLOOM_BLURH, // "bloomHorizontal" + BLOOM_BLUR_RADIUS, // "bloomRadius" + BLOOM_EXTRACT_BRIGHTNESS, // "bloomExtractBrightness" + BLOOM_STRENGTH, // "bloomStrength" + BLOOM_EXTRACT_EMISSIVE, // "bloomExtractEmissive" + BLOOM_EXTRACT_EMISSIVE2, // "bloomExtractEmissive2" + BLOOM_EXTRACT_ORM, // "bloomExtractORM" + BLOOM_EXTRACT_METAL, // "bloomExtractMetal" + BLOOM_EXTRACT_NONMETAL, // "bloomExtractNonMetal" + END_RESERVED_UNIFORMS } eGLSLReservedUniforms; // clang-format on diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index ac6db0b34f..2a0acab05a 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -345,7 +345,7 @@ public: void allocate(GLenum type, U32 size, GLuint& name, U8*& data) override { LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; - STOP_GLERROR; + llassert(type == GL_ARRAY_BUFFER || type == GL_ELEMENT_ARRAY_BUFFER); llassert(name == 0); // non zero name indicates a gl name that wasn't freed llassert(data == nullptr); // non null data indicates a buffer that wasn't freed @@ -355,10 +355,19 @@ public: { //allocate a new buffer LL_PROFILE_GPU_ZONE("vbo alloc"); - // ON OS X, we don't allocate a VBO until the last possible moment - // in unmapBuffer + data = (U8*) ll_aligned_malloc_16(size); - STOP_GLERROR; + + if (type == GL_ARRAY_BUFFER) + { + glGenBuffers(1, &name); + LLVertexBuffer::sGLRenderBuffer = name; + } + else + { + glGenBuffers(1, &name); + LLVertexBuffer::sGLRenderIndices = name; + } } } @@ -374,12 +383,12 @@ public: } mAllocated -= size; - STOP_GLERROR; + if (name) { delete_buffers(1, &name); } - STOP_GLERROR; + //LOG_GLERROR("LLAppleVBOPool::free()"); } }; @@ -783,7 +792,6 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; llassert(LLGLSLShader::sCurBoundShaderPtr != NULL); - STOP_GLERROR; gGL.syncMatrices(); @@ -909,10 +917,8 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi llassert(mGLBuffer == sGLRenderBuffer); llassert(mGLIndices == sGLRenderIndices); gGL.syncMatrices(); - STOP_GLERROR; glDrawRangeElements(sGLMode[mode], start, end, count, mIndicesType, (GLvoid*) (indices_offset * (size_t) mIndicesStride)); - STOP_GLERROR; } void LLVertexBuffer::drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const @@ -935,9 +941,8 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const llassert(mGLIndices == sGLRenderIndices); gGL.syncMatrices(); - STOP_GLERROR; glDrawArrays(sGLMode[mode], first, count); - STOP_GLERROR; + LOG_GLERROR("LLVertexBuffer::drawArrays()"); } //static @@ -970,10 +975,8 @@ void LLVertexBuffer::initClass(LLWindow* window) //static void LLVertexBuffer::unbind() { - STOP_GLERROR; glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - STOP_GLERROR; sGLRenderBuffer = 0; sGLRenderIndices = 0; } @@ -1366,7 +1369,7 @@ void LLVertexBuffer::flush_vbo(GLenum target, U32 start, U32 end, void* data, U8 // _mapBuffer to tag the buffer for flushing to GL _mapBuffer(); LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb memcpy"); - STOP_GLERROR; + //LOG_GLERROR("LLVertexBuffer::flush_vbo()"); // copy into mapped buffer memcpy(dst+start, data, end-start+1); } @@ -1412,7 +1415,6 @@ void LLVertexBuffer::_mapBuffer() void LLVertexBuffer::_unmapBuffer() { - STOP_GLERROR; if (!mMapped) { return; @@ -1428,14 +1430,14 @@ void LLVertexBuffer::_unmapBuffer() if (gGLManager.mIsApple) { - STOP_GLERROR; + LOG_GLERROR("LLVertexBuffer::_unmapBuffer() - apple 1"); if (mMappedData) { - if (mGLBuffer) + if(mGLBuffer == 0) { - delete_buffers(1, &mGLBuffer); + LL_WARNS() << "mGLBuffer is ZERO in unmapbuffer" << LL_ENDL; + glGenBuffers(1, &mGLBuffer); } - mGLBuffer = gen_buffer(); glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); sGLRenderBuffer = mGLBuffer; glBufferData(GL_ARRAY_BUFFER, mSize, mMappedData, GL_STATIC_DRAW); @@ -1445,16 +1447,16 @@ void LLVertexBuffer::_unmapBuffer() glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); sGLRenderBuffer = mGLBuffer; } - STOP_GLERROR; + LOG_GLERROR("LLVertexBuffer::_unmapBuffer() - apple 2"); if (mMappedIndexData) { - if (mGLIndices) + if (mGLIndices == 0) { - delete_buffers(1, &mGLIndices); + LL_WARNS() << "mGLIndices is ZERO in unmapbuffer" << LL_ENDL; + glGenBuffers(1, &mGLIndices); } - mGLIndices = gen_buffer(); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); sGLRenderIndices = mGLIndices; @@ -1465,7 +1467,7 @@ void LLVertexBuffer::_unmapBuffer() glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); sGLRenderIndices = mGLIndices; } - STOP_GLERROR; + LOG_GLERROR("LLVertexBuffer::_unmapBuffer() - apple 3"); } else { @@ -1656,11 +1658,10 @@ bool LLVertexBuffer::getClothWeightStrider(LLStrider& strider, U32 in // Set for rendering void LLVertexBuffer::setBuffer() { - STOP_GLERROR; if (mMapped) { - LL_WARNS_ONCE() << "Missing call to unmapBuffer or flushBuffers" << LL_ENDL; + LL_WARNS() << "Missing call to unmapBuffer or flushBuffers" << LL_ENDL; _unmapBuffer(); } @@ -1674,12 +1675,15 @@ void LLVertexBuffer::setBuffer() U32 data_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask; // this Vertex Buffer must provide all necessary attributes for currently bound shader - llassert_msg((data_mask & mTypeMask) == data_mask, - "Attribute mask mismatch! mTypeMask should be a superset of data_mask. data_mask: 0x" - << std::hex << data_mask << " mTypeMask: 0x" << mTypeMask << " Missing: 0x" << (data_mask & ~mTypeMask) << std::dec); + llassert_msg((data_mask & mTypeMask) == data_mask, "Attribute mask mismatch! mTypeMask should be a superset of data_mask. data_mask: 0x" << std::hex << data_mask << " mTypeMask: 0x" << mTypeMask << " Missing: 0x" << (data_mask & ~mTypeMask) << std::dec); if (sGLRenderBuffer != mGLBuffer) { + if(mGLBuffer == 0) + { + LL_WARNS() << "mGLBuffer is ZERO: sGLRenderBuffer=" << sGLRenderBuffer << LL_ENDL; + } + glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); sGLRenderBuffer = mGLBuffer; @@ -1697,14 +1701,14 @@ void LLVertexBuffer::setBuffer() sGLRenderIndices = mGLIndices; } - STOP_GLERROR; + LOG_GLERROR("LLVertexBuffer::setBuffer()"); } // virtual (default) void LLVertexBuffer::setupVertexBuffer() { - STOP_GLERROR; + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer()"); U8* base = nullptr; AttributeType loc; @@ -1712,98 +1716,141 @@ void LLVertexBuffer::setupVertexBuffer() U32 data_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask; + if (data_mask & MAP_VERTEX) + { + loc = TYPE_VERTEX; + ptr = (void*)(base + mOffsets[TYPE_VERTEX]); + glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_VERTEX"); + } + if (data_mask & MAP_NORMAL) { loc = TYPE_NORMAL; ptr = (void*)(base + mOffsets[TYPE_NORMAL]); glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_NORMAL"); } - if (data_mask & MAP_TEXCOORD3) - { - loc = TYPE_TEXCOORD3; - ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]); - glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr); - } - if (data_mask & MAP_TEXCOORD2) + + if (data_mask & MAP_TEXCOORD0) { - loc = TYPE_TEXCOORD2; - ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]); - glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr); + loc = TYPE_TEXCOORD0; + //glEnableVertexAttribArray(loc); + ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]); + glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_TEXCOORD0"); } + if (data_mask & MAP_TEXCOORD1) { loc = TYPE_TEXCOORD1; ptr = (void*)(base + mOffsets[TYPE_TEXCOORD1]); glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_TEXCOORD1"); } - if (data_mask & MAP_TANGENT) + + if (data_mask & MAP_TEXCOORD2) { - loc = TYPE_TANGENT; - ptr = (void*)(base + mOffsets[TYPE_TANGENT]); - glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr); + loc = TYPE_TEXCOORD2; + ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]); + glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_TEXCOORD2"); } - if (data_mask & MAP_TEXCOORD0) + + if (data_mask & MAP_TEXCOORD3) { - loc = TYPE_TEXCOORD0; - ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]); - glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr); + loc = TYPE_TEXCOORD3; + ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]); + glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_TEXCOORD3"); } + if (data_mask & MAP_COLOR) { loc = TYPE_COLOR; //bind emissive instead of color pointer if emissive is present ptr = (data_mask & MAP_EMISSIVE) ? (void*)(base + mOffsets[TYPE_EMISSIVE]) : (void*)(base + mOffsets[TYPE_COLOR]); glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_COLOR"); } + if (data_mask & MAP_EMISSIVE) { loc = TYPE_EMISSIVE; ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]); glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_EMISSIVE"); + if (!(data_mask & MAP_COLOR)) { //map emissive to color channel when color is not also being bound to avoid unnecessary shader swaps loc = TYPE_COLOR; glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_COLOR"); } } + + if (data_mask & MAP_TANGENT) + { + loc = TYPE_TANGENT; + ptr = (void*)(base + mOffsets[TYPE_TANGENT]); + glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_TANGENT"); + } + if (data_mask & MAP_WEIGHT) { loc = TYPE_WEIGHT; ptr = (void*)(base + mOffsets[TYPE_WEIGHT]); glVertexAttribPointer(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_WEIGHT"); } + if (data_mask & MAP_WEIGHT4) { loc = TYPE_WEIGHT4; ptr = (void*)(base + mOffsets[TYPE_WEIGHT4]); glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_WEIGHT4"); } - if (data_mask & MAP_JOINT) - { - loc = TYPE_JOINT; - ptr = (void*)(base + mOffsets[TYPE_JOINT]); - glVertexAttribIPointer(loc, 4, GL_UNSIGNED_SHORT, LLVertexBuffer::sTypeSize[TYPE_JOINT], ptr); - } + if (data_mask & MAP_CLOTHWEIGHT) { loc = TYPE_CLOTHWEIGHT; ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]); glVertexAttribPointer(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_CLOTHWEIGHT"); } + + if (data_mask & MAP_JOINT) + { + loc = TYPE_JOINT; + ptr = (void*)(base + mOffsets[TYPE_JOINT]); + glVertexAttribIPointer(loc, 4, GL_UNSIGNED_SHORT, LLVertexBuffer::sTypeSize[TYPE_JOINT], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_JOINT"); + } + if (data_mask & MAP_TEXTURE_INDEX) { loc = TYPE_TEXTURE_INDEX; ptr = (void*)(base + mOffsets[TYPE_VERTEX] + 12); glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_TEXTURE_INDEX"); } - if (data_mask & MAP_VERTEX) - { - loc = TYPE_VERTEX; - ptr = (void*)(base + mOffsets[TYPE_VERTEX]); - glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); - } - STOP_GLERROR; } void LLVertexBuffer::setPositionData(const LLVector4a* data) -- cgit v1.2.3 From ccf0114f36968d6cf6dfb11e1c5a035406314924 Mon Sep 17 00:00:00 2001 From: mobserveur Date: Mon, 8 Sep 2025 17:26:53 +0200 Subject: Optimisations and experimental HDR display support on mac This commit completes the previous ones for performance optimisations, and adds HDR display support on mac --- indra/llrender/llimagegl.cpp | 2 ++ indra/llrender/llrender.cpp | 17 ++++++----- indra/llrender/llrendertarget.cpp | 2 +- indra/llrender/llshadermgr.cpp | 2 ++ indra/llrender/llshadermgr.h | 2 ++ indra/llrender/llvertexbuffer.cpp | 61 +++++++++++++++++++++++++++++---------- indra/llrender/llvertexbuffer.h | 5 +++- 7 files changed, 67 insertions(+), 24 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 42af68c276..9ff483b92b 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -357,7 +357,9 @@ S32 LLImageGL::dataFormatBits(S32 dataformat) case GL_BGRA: return 32; // Used for QuickTime media textures on the Mac #endif case GL_DEPTH_COMPONENT: return 24; + case GL_DEPTH_COMPONENT16: return 16; case GL_DEPTH_COMPONENT24: return 24; + case GL_DEPTH_COMPONENT32: return 32; case GL_RGBA16: return 64; case GL_R16F: return 16; case GL_RG16F: return 32; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index d0e268f08c..5d26a69d7b 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -530,7 +530,9 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio { if (LLImageGL::sGlobalUseAnisotropic && option == TFO_ANISOTROPIC) { - glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, gGLManager.mMaxAnisotropy); + //glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, gGLManager.mMaxAnisotropy); + //We plan to add a setting. For now we stick to a low value. + glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 4.0); } else { @@ -1592,7 +1594,6 @@ void LLRender::end(std::string comment_) void LLRender::flush(std::string comment_) { - LOG_GLERROR("LLRender::flush() begin " + comment_); if (mCount > 0) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; @@ -1661,9 +1662,9 @@ void LLRender::flush(std::string comment_) } resetStriders(count); - } - LOG_GLERROR("LLRender::flush() end " + comment_); + LOG_GLERROR("LLRender::flush() end " + comment_); + } } LLVertexBuffer* LLRender::bufferfromCache(U32 attribute_mask, U32 count) @@ -1760,9 +1761,11 @@ LLVertexBuffer* LLRender::genBuffer(U32 attribute_mask, S32 count) vb->setColorData(mColorsp.get()); } -#if LL_DARWIN - vb->unmapBuffer(); -#endif + if(gGLManager.mIsApple && LLVertexBuffer::getVertexBufferMode() == 0) + { + vb->unmapBuffer(); + } + vb->unbind(); return vb; diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 957c85b606..4fd32620e1 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -368,7 +368,7 @@ bool LLRenderTarget::allocateDepth() U32 internal_type = LLTexUnit::getInternalType(mUsage); - LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_FLOAT, NULL, false); + 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); sBytesAllocated += mResX*mResY*4; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 3bc71a7413..fa1c686e8e 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1512,6 +1512,8 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("bloomExtractORM"); mReservedUniforms.push_back("bloomExtractMetal"); mReservedUniforms.push_back("bloomExtractNonMetal"); + mReservedUniforms.push_back("bloomClampValue"); + mReservedUniforms.push_back("mpHDRBoost"); llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 8b0bfc6bbe..19416066a5 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -352,6 +352,8 @@ public: BLOOM_EXTRACT_ORM, // "bloomExtractORM" BLOOM_EXTRACT_METAL, // "bloomExtractMetal" BLOOM_EXTRACT_NONMETAL, // "bloomExtractNonMetal" + BLOOM_CLAMP, // "bloomClampValue" + MP_HDR_BOOST, // "mpHDRBoost" END_RESERVED_UNIFORMS } eGLSLReservedUniforms; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 2a0acab05a..040dde7317 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -29,7 +29,6 @@ #include "llfasttimer.h" #include "llsys.h" #include "llvertexbuffer.h" -// #include "llrender.h" #include "llglheaders.h" #include "llrender.h" #include "llvector4a.h" @@ -272,13 +271,13 @@ static GLuint gen_buffer() { LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("gen buffer"); sIndex = pool_size; -#if !LL_DARWIN +//#if !LL_DARWIN if (!gGLManager.mIsAMD) { glGenBuffers(pool_size, sNamePool); } else -#endif +//#endif { // work around for AMD driver bug for (U32 i = 0; i < pool_size; ++i) { @@ -615,6 +614,8 @@ public: static LLVBOPool* sVBOPool = nullptr; +static U32 sMPVertexBufferMode = 0; + void LLVertexBufferData::drawWithMatrix() { if (!mVB) @@ -946,11 +947,13 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const } //static -void LLVertexBuffer::initClass(LLWindow* window) +void LLVertexBuffer::initClass(LLWindow* window, U32 mode_) { llassert(sVBOPool == nullptr); - if (gGLManager.mIsApple) + sMPVertexBufferMode = mode_; + + if (mode_ == 0 && gGLManager.mIsApple) { LL_INFOS() << "VBO Pooling Disabled" << LL_ENDL; sVBOPool = new LLAppleVBOPool(); @@ -972,6 +975,12 @@ void LLVertexBuffer::initClass(LLWindow* window) #endif } +//static +U32 LLVertexBuffer::getVertexBufferMode() +{ + return sMPVertexBufferMode; +} + //static void LLVertexBuffer::unbind() { @@ -1291,7 +1300,7 @@ U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 inde count = mNumVerts - index; } - if (!gGLManager.mIsApple) + if (!gGLManager.mIsApple || sMPVertexBufferMode == 1) { U32 start = mOffsets[type] + sTypeSize[type] * index; U32 end = start + sTypeSize[type] * count-1; @@ -1328,7 +1337,7 @@ U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count) count = mNumIndices-index; } - if (!gGLManager.mIsApple) + if (!gGLManager.mIsApple || sMPVertexBufferMode == 1) { U32 start = sizeof(U16) * index; U32 end = start + sizeof(U16) * count-1; @@ -1365,13 +1374,35 @@ void LLVertexBuffer::flush_vbo(GLenum target, U32 start, U32 end, void* data, U8 { if (gGLManager.mIsApple) { - // on OS X, flush_vbo doesn't actually write to the GL buffer, so be sure to call - // _mapBuffer to tag the buffer for flushing to GL - _mapBuffer(); - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb memcpy"); - //LOG_GLERROR("LLVertexBuffer::flush_vbo()"); - // copy into mapped buffer - memcpy(dst+start, data, end-start+1); + if(sMPVertexBufferMode == 1) + { + //LL_WARNS() << "flush_vbo mode 1" << LL_ENDL; + + U32 MapBits = GL_MAP_WRITE_BIT; + //U32 MapBits = GL_MAP_READ_BIT; + U32 buffer_size = end-start+1; + + U8 * mptr = NULL; + mptr = (U8*) glMapBufferRange( target, start, end-start+1, MapBits); + + if (mptr) + { + std::memcpy(mptr, (U8*) data, buffer_size); + if(!glUnmapBuffer(target)) LL_WARNS() << "glUnmapBuffer() failed" << LL_ENDL; + } + else LL_WARNS() << "glMapBufferRange() returned NULL" << LL_ENDL; + + } + else + { + //LL_WARNS() << "flush_vbo mode 0" << LL_ENDL; + // on OS X, flush_vbo doesn't actually write to the GL buffer, so be sure to call + // _mapBuffer to tag the buffer for flushing to GL + _mapBuffer(); + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb memcpy"); + // copy into mapped buffer + memcpy(dst+start, data, end-start+1); + } } else { @@ -1428,7 +1459,7 @@ void LLVertexBuffer::_unmapBuffer() } }; - if (gGLManager.mIsApple) + if (gGLManager.mIsApple && sMPVertexBufferMode == 0) { LOG_GLERROR("LLVertexBuffer::_unmapBuffer() - apple 1"); if (mMappedData) diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 375ad76fb8..4239477b8d 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -109,7 +109,7 @@ public: return *this; } - static void initClass(LLWindow* window); + static void initClass(LLWindow* window, U32 mode_ = 0); static void cleanupClass(); static void setupClientArrays(U32 data_mask); static void drawArrays(U32 mode, const std::vector& pos); @@ -128,6 +128,9 @@ public: // flush any pending mapped buffers static void flushBuffers(); + static U32 getVertexBufferMode(); + + //WARNING -- when updating these enums you MUST // 1 - update LLVertexBuffer::sTypeSize // 2 - update LLVertexBuffer::vb_type_name -- cgit v1.2.3 From 317dcdea1ca8d1f540187af47fc23a36ad8232aa Mon Sep 17 00:00:00 2001 From: mobserveur Date: Sat, 30 Aug 2025 01:59:43 +0200 Subject: Performance Optimisations, Bloom effect, Visuals Panel This commit contains performance optimisations in the the pipeline, framebuffer, vertexbuffer, reflection probes, shadows. It also fixes many opengl errors, modifies the opengl debugging, and adds a visuals effects panel. --- indra/llrender/llcubemaparray.cpp | 3 + indra/llrender/llgl.cpp | 14 +-- indra/llrender/llgl.h | 13 ++- indra/llrender/llimagegl.cpp | 7 +- indra/llrender/llrender.cpp | 68 +++++++++---- indra/llrender/llrender.h | 3 +- indra/llrender/llrender2dutils.cpp | 3 +- indra/llrender/llrendertarget.cpp | 193 ++++++++++++++++++++++++++++++------- indra/llrender/llrendertarget.h | 11 ++- indra/llrender/llshadermgr.cpp | 14 ++- indra/llrender/llshadermgr.h | 12 +++ indra/llrender/llvertexbuffer.cpp | 167 ++++++++++++++++++++------------ 12 files changed, 376 insertions(+), 132 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp index fb35e002df..e0a8782c33 100644 --- a/indra/llrender/llcubemaparray.cpp +++ b/indra/llrender/llcubemaparray.cpp @@ -114,6 +114,8 @@ LLCubeMapArray::LLCubeMapArray(LLCubeMapArray& lhs, U32 width, U32 count) : mTex allocate(mWidth, lhs.mImage->getComponents(), count, lhs.mImage->getUseMipMaps(), lhs.mHDR); // Copy each cubemap from the incoming array to the new array + // The call to glTexSubImage3D causes an INVALID OPERATION OpenGL error. For now we comment this.. + /* U32 min_count = std::min(count, lhs.mCount); for (U32 i = 0; i < min_count * 6; ++i) { @@ -133,6 +135,7 @@ LLCubeMapArray::LLCubeMapArray(LLCubeMapArray& lhs, U32 width, U32 count) : mTex glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, i, mWidth, mWidth, 1, components, GL_UNSIGNED_BYTE, scaled_image->getData()); } } + */ } LLCubeMapArray::~LLCubeMapArray() diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index ac66faaf5a..cc619e2086 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -2279,26 +2279,28 @@ void rotate_quat(LLQuaternion& rotation) void flush_glerror() { + if(!gDebugGL) return; glGetError(); } -//this function outputs gl error to the log file, does not crash the code. -void log_glerror() +void log_glerror(std::string comment) { + if(!gDebugGL) return; + if (LL_UNLIKELY(!gGLManager.mInited)) { return ; } - // Create or update texture to be used with this data + GLenum error; error = glGetError(); - while (LL_UNLIKELY(error)) + if (error != GL_NO_ERROR) { #if GLU_VERSION_1_1 GLubyte const * gl_error_msg = gluErrorString(error); if (NULL != gl_error_msg) { - LL_WARNS() << "GL Error: " << error << " GL Error String: " << gl_error_msg << LL_ENDL ; + LL_WARNS() << "GL Error (" << comment << ")" << error << ": " << gl_error_msg << LL_ENDL; } else #endif // GLU_VERSION_1_1 @@ -2307,7 +2309,6 @@ void log_glerror() // you'll probably have to grep for the number in glext.h. LL_WARNS() << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << LL_ENDL; } - error = glGetError(); } } @@ -2385,6 +2386,7 @@ void assert_glerror() void clear_glerror() { + if(!gDebugGL) return; glGetError(); glGetError(); } diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index bf8368a7b3..130b06f9df 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -154,17 +154,20 @@ void rotate_quat(LLQuaternion& rotation); void flush_glerror(); // Flush GL errors when we know we're handling them correctly. -void log_glerror(); +void log_glerror(std::string comment); void assert_glerror(); void clear_glerror(); -#if !LL_RELEASE_FOR_DOWNLOAD -# define stop_glerror() assert_glerror() -# define llglassertok() assert_glerror() -# define STOP_GLERROR stop_glerror() +//#if !LL_RELEASE_FOR_DOWNLOAD +#if 1 +# define LOG_GLERROR(COMMENT) log_glerror(COMMENT) +# define stop_glerror() log_glerror("stop") +# define llglassertok() log_glerror("ASSERTOK") +# define STOP_GLERROR log_glerror("STOP") #else +# define LOG_GLERROR(COMMENT) # define stop_glerror() # define llglassertok() # define STOP_GLERROR diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 558c3b062a..42af68c276 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -358,6 +358,7 @@ S32 LLImageGL::dataFormatBits(S32 dataformat) #endif case GL_DEPTH_COMPONENT: return 24; case GL_DEPTH_COMPONENT24: return 24; + case GL_RGBA16: return 64; case GL_R16F: return 16; case GL_RG16F: return 32; case GL_RGB16F: return 48; @@ -1290,7 +1291,7 @@ bool LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_ { glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height); mGLTextureCreated = true; - stop_glerror(); + LOG_GLERROR("LLImageGL::setSubImageFromFrameBuffer()"); return true; } else @@ -2583,6 +2584,8 @@ bool LLImageGL::scaleDown(S32 desired_discard) return false; } + //LL_WARNS() << "scaleDown" << LL_ENDL; + S32 mip = desired_discard - mCurrentDiscardLevel; S32 desired_width = getWidth(desired_discard); @@ -2600,6 +2603,7 @@ bool LLImageGL::scaleDown(S32 desired_discard) free_tex_image(mTexName); glTexImage2D(mTarget, 0, mFormatInternal, desired_width, desired_height, 0, mFormatPrimary, mFormatType, nullptr); glCopyTexSubImage2D(mTarget, 0, 0, 0, 0, 0, desired_width, desired_height); + LOG_GLERROR("LLImageGL::scaleDown() - glCopyTexSubImage2D"); alloc_tex_image(desired_width, desired_height, mFormatInternal, 1); mTexOptionsDirty = true; @@ -2609,6 +2613,7 @@ bool LLImageGL::scaleDown(S32 desired_discard) LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glGenerateMipmap"); gGL.getTexUnit(0)->bind(this); glGenerateMipmap(mTarget); + LOG_GLERROR("LLImageGL::scaleDown() - glGenerateMipmap"); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } } diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index cbb178b6f8..70993393ff 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -203,6 +203,7 @@ void LLTexUnit::bindFast(LLTexture* texture) glActiveTexture(GL_TEXTURE0 + mIndex); gGL.mCurrTextureUnitIndex = mIndex; mCurrTexture = gl_tex->getTexName(); + mCurrTexType = gl_tex->getTarget(); if (!mCurrTexture) { LL_PROFILE_ZONE_NAMED("MISSING TEXTURE"); @@ -479,41 +480,49 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio { if (mIndex < 0 || mCurrTexture == 0 || mCurrTexType == LLTexUnit::TT_MULTISAMPLE_TEXTURE) return; + GLenum target = sGLTextureType[mCurrTexType]; + + if (mCurrTexType == LLTexUnit::TT_NONE) + { + LL_WARNS() << "setTextureFilteringOption() Error: mCurrTexType==TT_NONE texture: " << mCurrTexture << LL_ENDL; + gGL.debugTexUnits(); + } + gGL.flush(); if (option == TFO_POINT) { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } else { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } if (option >= TFO_TRILINEAR && mHasMipMaps) { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } else if (option >= TFO_BILINEAR) { if (mHasMipMaps) { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); } else { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } } else { if (mHasMipMaps) { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); } else { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } } @@ -521,11 +530,11 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio { if (LLImageGL::sGlobalUseAnisotropic && option == TFO_ANISOTROPIC) { - glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, gGLManager.mMaxAnisotropy); + glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, gGLManager.mMaxAnisotropy); } else { - glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); + glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); } } } @@ -908,13 +917,12 @@ bool LLRender::init(bool needs_vertex_buffer) void LLRender::initVertexBuffer() { llassert_always(mBuffer.isNull()); - stop_glerror(); mBuffer = new LLVertexBuffer(immediate_mask); - mBuffer->allocateBuffer(4096, 0); + mBuffer->allocateBuffer(16384, 0); mBuffer->getVertexStrider(mVerticesp); mBuffer->getTexCoord0Strider(mTexcoordsp); mBuffer->getColorStrider(mColorsp); - stop_glerror(); + LOG_GLERROR("LLRender::initVertexBuffer()"); } void LLRender::resetVertexBuffer() @@ -1000,7 +1008,6 @@ void LLRender::syncLightState() void LLRender::syncMatrices() { - STOP_GLERROR; LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; static const U32 name[] = @@ -1145,7 +1152,7 @@ void LLRender::syncMatrices() syncLightState(); } } - STOP_GLERROR; + LOG_GLERROR("LLRender::syncMatrices()"); } void LLRender::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z) @@ -1555,7 +1562,7 @@ void LLRender::begin(const GLuint& mode) mMode == LLRender::TRIANGLES || mMode == LLRender::POINTS) { - flush(); + flush("LLRender::begin"); } else if (mCount != 0) { @@ -1566,7 +1573,7 @@ void LLRender::begin(const GLuint& mode) } } -void LLRender::end() +void LLRender::end(std::string comment_) { if (mCount == 0) { @@ -1579,13 +1586,13 @@ void LLRender::end() mMode != LLRender::POINTS) || mCount > 2048) { - flush(); + flush("from end " + comment_); } } -void LLRender::flush() +void LLRender::flush(std::string comment_) { - STOP_GLERROR; + LOG_GLERROR("LLRender::flush() begin " + comment_); if (mCount > 0) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; @@ -1655,6 +1662,13 @@ void LLRender::flush() resetStriders(count); } + + LOG_GLERROR("LLRender::flush() end " + comment_); +} + +void LLRender::flush() +{ + flush(""); } LLVertexBuffer* LLRender::bufferfromCache(U32 attribute_mask, U32 count) @@ -2026,7 +2040,8 @@ void LLRender::debugTexUnits(void) std::string active_enabled = "false"; for (U32 i = 0; i < mTexUnits.size(); i++) { - if (getTexUnit(i)->mCurrTexType != LLTexUnit::TT_NONE) + //if (getTexUnit(i)->mCurrTexType != LLTexUnit::TT_NONE) + if(1) { if (i == mCurrTextureUnitIndex) active_enabled = "true"; LL_INFOS("TextureUnit") << "TexUnit: " << i << " Enabled" << LL_ENDL; @@ -2044,8 +2059,19 @@ void LLRender::debugTexUnits(void) case LLTexUnit::TT_CUBE_MAP: LL_CONT << "Cube Map"; break; + case LLTexUnit::TT_CUBE_MAP_ARRAY: + LL_CONT << "Cube Map Array"; + break; + + case LLTexUnit::TT_MULTISAMPLE_TEXTURE: + LL_CONT << "Multisample Texture"; + break; + + case LLTexUnit::TT_TEXTURE_3D: + LL_CONT << "Texture 3D"; + break; default: - LL_CONT << "ARGH!!! NONE!"; + LL_CONT << "ARGH!!! NONE! -> type = " << getTexUnit(i)->mCurrTexType; break; } LL_CONT << ", Texture Bound: " << getTexUnit(i)->mCurrTexture << LL_ENDL; diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 97c47bcae9..a755ddd2b1 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -421,6 +421,7 @@ public: LLVector3 getUITranslation(); LLVector3 getUIScale(); + void flush(std::string comment_); void flush(); // if list is set, will store buffers in list for later use, if list isn't set, will use cache @@ -428,7 +429,7 @@ public: void endList(); void begin(const GLuint& mode); - void end(); + void end(std::string comment_ = ""); U8 getMode() const { return mMode; } diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index 9144ce6d62..714df863cd 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -833,8 +833,7 @@ void gl_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& c { gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], color.mV[VALPHA]); - gGL.flush(); - glLineWidth(2.5f); + LLRender2D::setLineWidth(2.5f); gGL.begin(LLRender::LINES); { diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 0e4aa2ee7a..ddb2bf5df7 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -158,6 +158,8 @@ void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name) llassert(mTex.empty()); // mTex must be empty with this mode (binding target should be done via LLImageGL) llassert(!isBoundInStack()); + U32 target = getTarget(); + if (mFBO == 0) { glGenFramebuffers(1, (GLuint*)&mFBO); @@ -174,14 +176,14 @@ void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name) mTex.push_back(use_name); - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + glBindFramebuffer(target, mFBO); + glFramebufferTexture2D(target, GL_COLOR_ATTACHMENT0, LLTexUnit::getInternalType(mUsage), use_name, 0); stop_glerror(); check_framebuffer_status(); - glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); + glBindFramebuffer(target, sCurFBO); } void LLRenderTarget::releaseColorAttachment() @@ -194,6 +196,7 @@ void LLRenderTarget::releaseColorAttachment() glBindFramebuffer(GL_FRAMEBUFFER, mFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, LLTexUnit::getInternalType(mUsage), 0, 0); glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); + LOG_GLERROR(mName + " releaseColorAttachment()"); mTex.clear(); } @@ -208,6 +211,8 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) return true; } + U32 target = getTarget(); + U32 offset = static_cast(mTex.size()); if( offset >= 4 ) @@ -226,12 +231,76 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) LLImageGL::generateTextures(1, &tex); gGL.getTexUnit(0)->bindManual(mUsage, tex); - stop_glerror(); - + U32 miplevel = mMipLevels; + U32 intformat = color_fmt; + U32 pixformat = GL_RGBA; + U32 pixtype = GL_UNSIGNED_BYTE; { - clear_glerror(); - LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false); + //clear_glerror(); + + if(color_fmt == GL_RGB10_A2) + { + pixformat = GL_RGBA; + pixtype = GL_UNSIGNED_BYTE; + } + else if(color_fmt == GL_R11F_G11F_B10F) + { + pixformat = GL_RGB; + pixtype = GL_HALF_FLOAT; + } + else if(color_fmt == GL_R8) + { + pixformat = GL_RED; + pixtype = GL_UNSIGNED_BYTE; + } + else if(color_fmt == GL_R16F) + { + pixformat = GL_RED; + pixtype = GL_HALF_FLOAT; + } + else if(color_fmt == GL_RG16F) + { + pixformat = GL_RG; + pixtype = GL_HALF_FLOAT; + } + else if(color_fmt == GL_RGBA16F) + { + pixformat = GL_RGBA; + pixtype = GL_HALF_FLOAT; + } + else if(color_fmt == GL_RGB16F) + { + pixformat = GL_RGB; + pixtype = GL_HALF_FLOAT; + } + else if(color_fmt == GL_RGB8) + { + pixformat = GL_RGB; + pixtype = GL_UNSIGNED_BYTE; + } + else if(color_fmt == GL_RGB) + { + pixformat = GL_RGB; + pixtype = GL_UNSIGNED_BYTE; + } + else if(color_fmt == GL_RGBA) + { + pixformat = GL_RGBA; + pixtype = GL_UNSIGNED_BYTE; + } + else if(color_fmt == GL_RGBA8) + { + pixformat = GL_RGBA; + pixtype = GL_UNSIGNED_BYTE; + } + else + { + pixformat = GL_RGBA; + pixtype = GL_UNSIGNED_BYTE; + } + + LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, pixformat, pixtype, NULL, false); if (glGetError() != GL_NO_ERROR) { LL_WARNS() << "Could not allocate color buffer for render target." << LL_ENDL; @@ -241,32 +310,30 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) sBytesAllocated += mResX*mResY*4; - stop_glerror(); - - if (offset == 0) { //use bilinear filtering on single texture render targets that aren't multisampled gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - stop_glerror(); + LOG_GLERROR(mName + " setting filtering to TFO_BILINEAR"); } else { //don't filter data attachments gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - stop_glerror(); + LOG_GLERROR(mName + " setting filtering to TFO_POINT"); } #if GL_VERSION_3_1 if (mUsage != LLTexUnit::TT_RECT_TEXTURE) { gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); - stop_glerror(); + LOG_GLERROR(mName + " setting address mode to TAM_MIRROR"); + } else #endif { // ATI doesn't support mirrored repeat for rectangular textures. gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - stop_glerror(); + LOG_GLERROR(mName + " setting address mode to TAM_CLAMP"); } if (mFBO) @@ -285,7 +352,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) if (gDebugGL) { //bind and unbind to validate target - bindTarget(); + bindTarget(mName, mMode); flush(); } @@ -300,16 +367,15 @@ bool LLRenderTarget::allocateDepth() gGL.getTexUnit(0)->bindManual(mUsage, mDepth); 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, false); + + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_FLOAT, NULL, false); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); sBytesAllocated += mResX*mResY*4; if (glGetError() != GL_NO_ERROR) { - LL_WARNS() << "Unable to allocate depth buffer for render target." << LL_ENDL; + LL_WARNS() << "Unable to allocate depth buffer for render target " << mName << LL_ENDL; return false; } @@ -345,6 +411,8 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); + LOG_GLERROR(mName + " shareDepthBuffer()"); + target.mUseDepth = true; } } @@ -408,19 +476,32 @@ void LLRenderTarget::release() LLImageGL::deleteTextures(1, &mTex[0]); } + LOG_GLERROR(mName + " release()"); + mTex.clear(); mInternalFormat.clear(); mResX = mResY = 0; } -void LLRenderTarget::bindTarget() +void LLRenderTarget::bindTarget(std::string name_, U32 mode_) { LL_PROFILE_GPU_ZONE("bindTarget"); llassert(mFBO); llassert(!isBoundInStack()); - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + //mode_ = 0; + + mMode = mode_; + mName = name_; + + U32 target = getTarget(); + + glBindFramebuffer(target, mFBO); + LOG_GLERROR(mName+" bindTarget()"); + + //attach(); + sCurFBO = mFBO; //setup multiple render targets @@ -431,16 +512,35 @@ void LLRenderTarget::bindTarget() if (mTex.empty()) { //no color buffer to draw to + if(!mUseDepth) LL_WARNS() << mName << " HAS NO COLOR BUFFER AND NO DEPTH!!" << LL_ENDL; GLenum buffers[] = {GL_NONE}; glDrawBuffers(0, buffers); glReadBuffer(GL_NONE); } - else + else if(mMode == 0) + { + glDrawBuffers(static_cast(mTex.size()), drawbuffers); + glReadBuffer(GL_COLOR_ATTACHMENT0); + + LOG_GLERROR(mName+" read and write buffers"); + + } + else if(mMode == 1) { glDrawBuffers(static_cast(mTex.size()), drawbuffers); + glReadBuffer(GL_NONE); + LOG_GLERROR(mName+" draw buffer"); + } + else if(mMode == 2) + { + GLenum buffers[] = {GL_NONE}; + glDrawBuffers(0, buffers); glReadBuffer(GL_COLOR_ATTACHMENT0); + LOG_GLERROR(mName+" read buffer"); } + check_framebuffer_status(); + LOG_GLERROR(mName+" checked status"); glViewport(0, 0, mResX, mResY); sCurResX = mResX; @@ -454,24 +554,22 @@ void LLRenderTarget::clear(U32 mask_in) { LL_PROFILE_GPU_ZONE("clear"); llassert(mFBO); - U32 mask = GL_COLOR_BUFFER_BIT; - if (mUseDepth) - { - mask |= GL_DEPTH_BUFFER_BIT; + U32 mask = 0; + + if(!mTex.empty()) mask |= GL_COLOR_BUFFER_BIT; + if (mUseDepth) mask |= GL_DEPTH_BUFFER_BIT; - } if (mFBO) { check_framebuffer_status(); - stop_glerror(); glClear(mask & mask_in); - stop_glerror(); + LOG_GLERROR(mName + "clear()"); } else { LLGLEnable scissor(GL_SCISSOR_TEST); glScissor(0, 0, mResX, mResY); - stop_glerror(); + LOG_GLERROR(""); glClear(mask & mask_in); } } @@ -514,29 +612,43 @@ void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilt } gGL.getTexUnit(channel)->setTextureFilteringOption(filter_options); + + LOG_GLERROR(mName + " bindTexture()"); } void LLRenderTarget::flush() { LL_PROFILE_GPU_ZONE("rt flush"); + + LOG_GLERROR(mName+" rt flush() A"); + gGL.flush(); llassert(mFBO); llassert(sCurFBO == mFBO); llassert(sBoundTarget == this); - if (mGenerateMipMaps == LLTexUnit::TMG_AUTO) + if (mGenerateMipMaps == LLTexUnit::TMG_AUTO && mMode != 2) { LL_PROFILE_GPU_ZONE("rt generate mipmaps"); - bindTexture(0, 0, LLTexUnit::TFO_TRILINEAR); + //bindTexture(0, 0, LLTexUnit::TFO_TRILINEAR); + bindTexture(0, 0, LLTexUnit::TFO_ANISOTROPIC); glGenerateMipmap(GL_TEXTURE_2D); + LOG_GLERROR(mName + " glGenerateMipmap()"); } + LOG_GLERROR(mName + " rt flush() B"); + + unbind(); +} + +void LLRenderTarget::unbind() +{ if (mPreviousRT) { // a bit hacky -- pop the RT stack back two frames and push // the previous frame back on to play nice with the GL state machine sBoundTarget = mPreviousRT->mPreviousRT; - mPreviousRT->bindTarget(); + mPreviousRT->bindTarget(mPreviousRT->mName, mPreviousRT->mMode); } else { @@ -547,9 +659,10 @@ void LLRenderTarget::flush() sCurResX = gGLViewport[2]; sCurResY = gGLViewport[3]; glReadBuffer(GL_BACK); - GLenum drawbuffers[] = {GL_BACK}; - glDrawBuffers(1, drawbuffers); + glDrawBuffer(GL_BACK); } + + LOG_GLERROR(mName + " rt unbind()"); } bool LLRenderTarget::isComplete() const @@ -604,3 +717,13 @@ void LLRenderTarget::swapFBORefs(LLRenderTarget& other) std::swap(mFBO, other.mFBO); std::swap(mTex, other.mTex); } + +U32 LLRenderTarget::getTarget() +{ + U32 target = GL_FRAMEBUFFER; + + if(mMode == 1) target = GL_DRAW_FRAMEBUFFER; + else if(mMode == 2) target = GL_READ_FRAMEBUFFER; + + return target; +} diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index cd3290cf66..ce3025f280 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -126,7 +126,7 @@ public: // If an LLRenderTarget is currently bound, stores a reference to that LLRenderTarget // and restores previous binding on flush() (maintains a stack of Render Targets) // Asserts that this target is not currently bound in the stack - void bindTarget(); + void bindTarget(std::string name_ = "nd", U32 mode_ = 0); //clear render targer, clears depth buffer if present, //uses scissor rect if in copy-to-texture mode @@ -158,6 +158,7 @@ public: // If an LLRenderTarget was bound when bindTarget was called, binds that RenderTarget for rendering (maintains RT stack) // asserts that this target is currently bound void flush(); + void unbind(); //Returns TRUE if target is ready to be rendered into. //That is, if the target has been allocated with at least @@ -174,11 +175,15 @@ public: static LLRenderTarget* sBoundTarget; + U32 mMode; + std::string mName; + protected: U32 mResX; U32 mResY; std::vector mTex; std::vector mInternalFormat; + std::vector mPixFormat; U32 mFBO; LLRenderTarget* mPreviousRT = nullptr; @@ -188,6 +193,10 @@ protected: U32 mMipLevels; LLTexUnit::eTextureType mUsage; + +private: + U32 getTarget(); + }; #endif diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 4807c12226..6a3f88f9d3 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -571,7 +571,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev } else { - shader_code_text[shader_code_count++] = strdup("#version 400\n"); + shader_code_text[shader_code_count++] = strdup("#version 410\n"); } } else if (major_version == 3) @@ -1501,6 +1501,18 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("searchTex"); mReservedUniforms.push_back("blendTex"); + mReservedUniforms.push_back("bloomEMap"); + mReservedUniforms.push_back("bloomBlurredMap"); + mReservedUniforms.push_back("bloomHorizontal"); + mReservedUniforms.push_back("bloomBlurRadius"); + mReservedUniforms.push_back("bloomExtractBrightness"); + mReservedUniforms.push_back("bloomStrength"); + mReservedUniforms.push_back("bloomExtractEmissive"); + mReservedUniforms.push_back("bloomExtractEmissive2"); + mReservedUniforms.push_back("bloomExtractORM"); + mReservedUniforms.push_back("bloomExtractMetal"); + mReservedUniforms.push_back("bloomExtractNonMetal"); + llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS); std::set dupe_check; diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 46788841a5..8b0bfc6bbe 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -341,6 +341,18 @@ public: SMAA_SEARCH_TEX, // "searchTex" SMAA_BLEND_TEX, // "blendTex" + BLOOM_EMAP, // "bloomEMap" + BLOOM_BMAP, // "bloomBlurredMap" + BLOOM_BLURH, // "bloomHorizontal" + BLOOM_BLUR_RADIUS, // "bloomRadius" + BLOOM_EXTRACT_BRIGHTNESS, // "bloomExtractBrightness" + BLOOM_STRENGTH, // "bloomStrength" + BLOOM_EXTRACT_EMISSIVE, // "bloomExtractEmissive" + BLOOM_EXTRACT_EMISSIVE2, // "bloomExtractEmissive2" + BLOOM_EXTRACT_ORM, // "bloomExtractORM" + BLOOM_EXTRACT_METAL, // "bloomExtractMetal" + BLOOM_EXTRACT_NONMETAL, // "bloomExtractNonMetal" + END_RESERVED_UNIFORMS } eGLSLReservedUniforms; // clang-format on diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index ac6db0b34f..43d780a383 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -345,7 +345,7 @@ public: void allocate(GLenum type, U32 size, GLuint& name, U8*& data) override { LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; - STOP_GLERROR; + llassert(type == GL_ARRAY_BUFFER || type == GL_ELEMENT_ARRAY_BUFFER); llassert(name == 0); // non zero name indicates a gl name that wasn't freed llassert(data == nullptr); // non null data indicates a buffer that wasn't freed @@ -355,10 +355,19 @@ public: { //allocate a new buffer LL_PROFILE_GPU_ZONE("vbo alloc"); - // ON OS X, we don't allocate a VBO until the last possible moment - // in unmapBuffer + data = (U8*) ll_aligned_malloc_16(size); - STOP_GLERROR; + + if (type == GL_ARRAY_BUFFER) + { + glGenBuffers(1, &name); + LLVertexBuffer::sGLRenderBuffer = name; + } + else + { + glGenBuffers(1, &name); + LLVertexBuffer::sGLRenderIndices = name; + } } } @@ -374,12 +383,12 @@ public: } mAllocated -= size; - STOP_GLERROR; + if (name) { delete_buffers(1, &name); } - STOP_GLERROR; + //LOG_GLERROR("LLAppleVBOPool::free()"); } }; @@ -783,7 +792,6 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; llassert(LLGLSLShader::sCurBoundShaderPtr != NULL); - STOP_GLERROR; gGL.syncMatrices(); @@ -909,10 +917,8 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi llassert(mGLBuffer == sGLRenderBuffer); llassert(mGLIndices == sGLRenderIndices); gGL.syncMatrices(); - STOP_GLERROR; glDrawRangeElements(sGLMode[mode], start, end, count, mIndicesType, (GLvoid*) (indices_offset * (size_t) mIndicesStride)); - STOP_GLERROR; } void LLVertexBuffer::drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const @@ -935,9 +941,8 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const llassert(mGLIndices == sGLRenderIndices); gGL.syncMatrices(); - STOP_GLERROR; glDrawArrays(sGLMode[mode], first, count); - STOP_GLERROR; + LOG_GLERROR("LLVertexBuffer::drawArrays()"); } //static @@ -970,10 +975,8 @@ void LLVertexBuffer::initClass(LLWindow* window) //static void LLVertexBuffer::unbind() { - STOP_GLERROR; glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - STOP_GLERROR; sGLRenderBuffer = 0; sGLRenderIndices = 0; } @@ -1366,7 +1369,7 @@ void LLVertexBuffer::flush_vbo(GLenum target, U32 start, U32 end, void* data, U8 // _mapBuffer to tag the buffer for flushing to GL _mapBuffer(); LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb memcpy"); - STOP_GLERROR; + //LOG_GLERROR("LLVertexBuffer::flush_vbo()"); // copy into mapped buffer memcpy(dst+start, data, end-start+1); } @@ -1412,7 +1415,6 @@ void LLVertexBuffer::_mapBuffer() void LLVertexBuffer::_unmapBuffer() { - STOP_GLERROR; if (!mMapped) { return; @@ -1428,14 +1430,14 @@ void LLVertexBuffer::_unmapBuffer() if (gGLManager.mIsApple) { - STOP_GLERROR; + LOG_GLERROR("LLVertexBuffer::_unmapBuffer() - apple 1"); if (mMappedData) { - if (mGLBuffer) + if(mGLBuffer == 0) { - delete_buffers(1, &mGLBuffer); + LL_WARNS() << "mGLBuffer is ZERO in unmapbuffer" << LL_ENDL; + glGenBuffers(1, &mGLBuffer); } - mGLBuffer = gen_buffer(); glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); sGLRenderBuffer = mGLBuffer; glBufferData(GL_ARRAY_BUFFER, mSize, mMappedData, GL_STATIC_DRAW); @@ -1445,16 +1447,16 @@ void LLVertexBuffer::_unmapBuffer() glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); sGLRenderBuffer = mGLBuffer; } - STOP_GLERROR; + LOG_GLERROR("LLVertexBuffer::_unmapBuffer() - apple 2"); if (mMappedIndexData) { - if (mGLIndices) + if (mGLIndices == 0) { - delete_buffers(1, &mGLIndices); + LL_WARNS() << "mGLIndices is ZERO in unmapbuffer" << LL_ENDL; + glGenBuffers(1, &mGLIndices); } - mGLIndices = gen_buffer(); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); sGLRenderIndices = mGLIndices; @@ -1465,7 +1467,7 @@ void LLVertexBuffer::_unmapBuffer() glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); sGLRenderIndices = mGLIndices; } - STOP_GLERROR; + LOG_GLERROR("LLVertexBuffer::_unmapBuffer() - apple 3"); } else { @@ -1656,11 +1658,10 @@ bool LLVertexBuffer::getClothWeightStrider(LLStrider& strider, U32 in // Set for rendering void LLVertexBuffer::setBuffer() { - STOP_GLERROR; if (mMapped) { - LL_WARNS_ONCE() << "Missing call to unmapBuffer or flushBuffers" << LL_ENDL; + LL_WARNS() << "Missing call to unmapBuffer or flushBuffers" << LL_ENDL; _unmapBuffer(); } @@ -1680,6 +1681,11 @@ void LLVertexBuffer::setBuffer() if (sGLRenderBuffer != mGLBuffer) { + if(mGLBuffer == 0) + { + LL_WARNS() << "mGLBuffer is ZERO: sGLRenderBuffer=" << sGLRenderBuffer << LL_ENDL; + } + glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); sGLRenderBuffer = mGLBuffer; @@ -1697,14 +1703,14 @@ void LLVertexBuffer::setBuffer() sGLRenderIndices = mGLIndices; } - STOP_GLERROR; + LOG_GLERROR("LLVertexBuffer::setBuffer()"); } // virtual (default) void LLVertexBuffer::setupVertexBuffer() { - STOP_GLERROR; + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer()"); U8* base = nullptr; AttributeType loc; @@ -1712,98 +1718,141 @@ void LLVertexBuffer::setupVertexBuffer() U32 data_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask; + if (data_mask & MAP_VERTEX) + { + loc = TYPE_VERTEX; + ptr = (void*)(base + mOffsets[TYPE_VERTEX]); + glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_VERTEX"); + } + if (data_mask & MAP_NORMAL) { loc = TYPE_NORMAL; ptr = (void*)(base + mOffsets[TYPE_NORMAL]); glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_NORMAL"); } - if (data_mask & MAP_TEXCOORD3) - { - loc = TYPE_TEXCOORD3; - ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]); - glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr); - } - if (data_mask & MAP_TEXCOORD2) + + if (data_mask & MAP_TEXCOORD0) { - loc = TYPE_TEXCOORD2; - ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]); - glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr); + loc = TYPE_TEXCOORD0; + //glEnableVertexAttribArray(loc); + ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]); + glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_TEXCOORD0"); } + if (data_mask & MAP_TEXCOORD1) { loc = TYPE_TEXCOORD1; ptr = (void*)(base + mOffsets[TYPE_TEXCOORD1]); glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_TEXCOORD1"); } - if (data_mask & MAP_TANGENT) + + if (data_mask & MAP_TEXCOORD2) { - loc = TYPE_TANGENT; - ptr = (void*)(base + mOffsets[TYPE_TANGENT]); - glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr); + loc = TYPE_TEXCOORD2; + ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]); + glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_TEXCOORD2"); } - if (data_mask & MAP_TEXCOORD0) + + if (data_mask & MAP_TEXCOORD3) { - loc = TYPE_TEXCOORD0; - ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]); - glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr); + loc = TYPE_TEXCOORD3; + ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]); + glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_TEXCOORD3"); } + if (data_mask & MAP_COLOR) { loc = TYPE_COLOR; //bind emissive instead of color pointer if emissive is present ptr = (data_mask & MAP_EMISSIVE) ? (void*)(base + mOffsets[TYPE_EMISSIVE]) : (void*)(base + mOffsets[TYPE_COLOR]); glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_COLOR"); } + if (data_mask & MAP_EMISSIVE) { loc = TYPE_EMISSIVE; ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]); glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_EMISSIVE"); + if (!(data_mask & MAP_COLOR)) { //map emissive to color channel when color is not also being bound to avoid unnecessary shader swaps loc = TYPE_COLOR; glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_COLOR"); } } + + if (data_mask & MAP_TANGENT) + { + loc = TYPE_TANGENT; + ptr = (void*)(base + mOffsets[TYPE_TANGENT]); + glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_TANGENT"); + } + if (data_mask & MAP_WEIGHT) { loc = TYPE_WEIGHT; ptr = (void*)(base + mOffsets[TYPE_WEIGHT]); glVertexAttribPointer(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_WEIGHT"); } + if (data_mask & MAP_WEIGHT4) { loc = TYPE_WEIGHT4; ptr = (void*)(base + mOffsets[TYPE_WEIGHT4]); glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_WEIGHT4"); } - if (data_mask & MAP_JOINT) - { - loc = TYPE_JOINT; - ptr = (void*)(base + mOffsets[TYPE_JOINT]); - glVertexAttribIPointer(loc, 4, GL_UNSIGNED_SHORT, LLVertexBuffer::sTypeSize[TYPE_JOINT], ptr); - } + if (data_mask & MAP_CLOTHWEIGHT) { loc = TYPE_CLOTHWEIGHT; ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]); glVertexAttribPointer(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_CLOTHWEIGHT"); } + + if (data_mask & MAP_JOINT) + { + loc = TYPE_JOINT; + ptr = (void*)(base + mOffsets[TYPE_JOINT]); + glVertexAttribIPointer(loc, 4, GL_UNSIGNED_SHORT, LLVertexBuffer::sTypeSize[TYPE_JOINT], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_JOINT"); + } + if (data_mask & MAP_TEXTURE_INDEX) { loc = TYPE_TEXTURE_INDEX; ptr = (void*)(base + mOffsets[TYPE_VERTEX] + 12); glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); + + LOG_GLERROR("LLVertexBuffer::setupVertexBuffer TYPE_TEXTURE_INDEX"); } - if (data_mask & MAP_VERTEX) - { - loc = TYPE_VERTEX; - ptr = (void*)(base + mOffsets[TYPE_VERTEX]); - glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); - } - STOP_GLERROR; } void LLVertexBuffer::setPositionData(const LLVector4a* data) -- cgit v1.2.3