diff options
Diffstat (limited to 'indra/llrender')
-rw-r--r-- | indra/llrender/llfontgl.cpp | 1 | ||||
-rw-r--r-- | indra/llrender/llglslshader.cpp | 41 | ||||
-rw-r--r-- | indra/llrender/llglslshader.h | 3 | ||||
-rw-r--r-- | indra/llrender/llimagegl.cpp | 1 | ||||
-rw-r--r-- | indra/llrender/llrender.cpp | 4 | ||||
-rw-r--r-- | indra/llrender/llrendertarget.cpp | 101 | ||||
-rw-r--r-- | indra/llrender/llrendertarget.h | 24 | ||||
-rw-r--r-- | indra/llrender/llshadermgr.cpp | 79 | ||||
-rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 246 | ||||
-rw-r--r-- | indra/llrender/llvertexbuffer.h | 51 |
10 files changed, 349 insertions, 202 deletions
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 13008292f6..d6a31dc862 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -271,7 +271,6 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons } } - const LLFontGlyphInfo* next_glyph = NULL; const S32 GLYPH_BATCH_SIZE = 30; diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 16534fa9a5..257bcd9380 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -55,7 +55,7 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2) LLShaderFeatures::LLShaderFeatures() : calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false), -hasTransport(false), hasSkinning(false), hasAtmospherics(false), isSpecular(false), +hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false), hasGamma(false), hasLighting(false), calculatesAtmospherics(false) { } @@ -118,7 +118,7 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes, { GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second); LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL; - if (mShaderLevel > 0) + if (shaderhandle > 0) { attachObject(shaderhandle); } @@ -698,17 +698,46 @@ void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, c GLint LLGLSLShader::getUniformLocation(const string& uniform) { + GLint ret = -1; if (mProgramObject > 0) { std::map<string, GLint>::iterator iter = mUniformMap.find(uniform); if (iter != mUniformMap.end()) { - llassert(iter->second == glGetUniformLocationARB(mProgramObject, uniform.c_str())); - return iter->second; + if (gDebugGL) + { + stop_glerror(); + if (iter->second != glGetUniformLocationARB(mProgramObject, uniform.c_str())) + { + llerrs << "Uniform does not match." << llendl; + } + stop_glerror(); + } + ret = iter->second; } } - return -1; + /*if (gDebugGL) + { + if (ret == -1 && ret != glGetUniformLocationARB(mProgramObject, uniform.c_str())) + { + llerrs << "Uniform map invalid." << llendl; + } + }*/ + + return ret; +} + +GLint LLGLSLShader::getAttribLocation(U32 attrib) +{ + if (attrib < mAttribute.size()) + { + return mAttribute[attrib]; + } + else + { + return -1; + } } void LLGLSLShader::uniform1i(const string& uniform, GLint v) @@ -882,7 +911,9 @@ void LLGLSLShader::uniformMatrix4fv(const string& uniform, U32 count, GLboolean if (location >= 0) { + stop_glerror(); glUniformMatrix4fvARB(location, count, transpose, v); + stop_glerror(); } } diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index c11bd50716..d46ddbbe18 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -42,6 +42,7 @@ public: bool hasWaterFog; // implies no gamma bool hasTransport; // implies no lighting (it's possible to have neither though) bool hasSkinning; + bool hasObjectSkinning; bool hasAtmospherics; bool hasGamma; @@ -103,7 +104,7 @@ public: void vertexAttrib4fv(U32 index, GLfloat* v); GLint getUniformLocation(const std::string& uniform); - + GLint getAttribLocation(U32 attrib); GLint mapUniformTextureChannel(GLint location, GLenum type); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 65940cb067..ac43b53ecc 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1716,6 +1716,7 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) sample[asum/(16*4)] += 4; } + rowstart += 2 * w * mAlphaStride; } length *= 2; // we sampled everything twice, essentially diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 8eb160f4e7..fb2d0bc7a7 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -898,7 +898,7 @@ LLVector3 LLRender::getUITranslation() { if (mUIOffset.empty()) { - return LLVector3::zero; + return LLVector3(0,0,0); } return mUIOffset.back(); } @@ -907,7 +907,7 @@ LLVector3 LLRender::getUIScale() { if (mUIScale.empty()) { - return LLVector3(1.f, 1.f, 1.f); + return LLVector3(1,1,1); } return mUIScale.back(); } diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 7205210fcc..ccbd027f30 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -50,7 +50,7 @@ void check_framebuffer_status() } } -BOOL LLRenderTarget::sUseFBO = FALSE; +bool LLRenderTarget::sUseFBO = false; LLRenderTarget::LLRenderTarget() : mResX(0), @@ -59,8 +59,8 @@ LLRenderTarget::LLRenderTarget() : mFBO(0), mDepth(0), mStencil(0), - mUseDepth(FALSE), - mRenderDepth(FALSE), + mUseDepth(false), + mRenderDepth(false), mUsage(LLTexUnit::TT_TEXTURE), mSamples(0), mSampleBuffer(NULL) @@ -78,7 +78,7 @@ void LLRenderTarget::setSampleBuffer(LLMultisampleBuffer* buffer) mSampleBuffer = buffer; } -void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo) +void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo) { stop_glerror(); mResX = resx; @@ -209,6 +209,16 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) llerrs << "Cannot share depth buffer between non FBO render targets." << llendl; } + if (target.mDepth) + { + llerrs << "Attempting to override existing depth buffer. Detach existing buffer first." << llendl; + } + + if (target.mUseDepth) + { + llerrs << "Attempting to override existing shared depth buffer. Detach existing buffer first." << llendl; + } + if (mDepth) { stop_glerror(); @@ -221,37 +231,21 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) stop_glerror(); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); stop_glerror(); + target.mStencil = true; } else { glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); stop_glerror(); - if (mStencil) - { - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); - stop_glerror(); - } } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - target.mUseDepth = TRUE; + target.mUseDepth = true; } } void LLRenderTarget::release() { - if (mFBO) - { - glDeleteFramebuffersEXT(1, (GLuint *) &mFBO); - mFBO = 0; - } - - if (mTex.size() > 0) - { - LLImageGL::deleteTextures(mTex.size(), &mTex[0]); - mTex.clear(); - } - if (mDepth) { if (mStencil) @@ -266,6 +260,33 @@ void LLRenderTarget::release() } mDepth = 0; } + else if (mUseDepth && mFBO) + { //detach shared depth buffer + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); + if (mStencil) + { //attached as a renderbuffer + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0); + mStencil = false; + } + else + { //attached as a texture + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), 0, 0); + } + mUseDepth = false; + } + + if (mFBO) + { + glDeleteFramebuffersEXT(1, (GLuint *) &mFBO); + mFBO = 0; + } + + if (mTex.size() > 0) + { + LLImageGL::deleteTextures(mTex.size(), &mTex[0]); + mTex.clear(); + } mSampleBuffer = NULL; sBoundTarget = NULL; @@ -349,19 +370,19 @@ U32 LLRenderTarget::getTexture(U32 attachment) const { llerrs << "Invalid attachment index." << llendl; } + if (mTex.empty()) + { + return 0; + } return mTex[attachment]; } void LLRenderTarget::bindTexture(U32 index, S32 channel) { - if (index > mTex.size()-1) - { - llerrs << "Invalid attachment index." << llendl; - } - gGL.getTexUnit(channel)->bindManual(mUsage, mTex[index]); + gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index)); } -void LLRenderTarget::flush(BOOL fetch_depth) +void LLRenderTarget::flush(bool fetch_depth) { gGL.flush(); if (!mFBO) @@ -497,9 +518,9 @@ void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0 } } -BOOL LLRenderTarget::isComplete() const +bool LLRenderTarget::isComplete() const { - return (!mTex.empty() || mDepth) ? TRUE : FALSE; + return (!mTex.empty() || mDepth) ? true : false; } void LLRenderTarget::getViewport(S32* viewport) @@ -520,10 +541,10 @@ LLMultisampleBuffer::LLMultisampleBuffer() LLMultisampleBuffer::~LLMultisampleBuffer() { - releaseSampleBuffer(); + release(); } -void LLMultisampleBuffer::releaseSampleBuffer() +void LLMultisampleBuffer::release() { if (mFBO) { @@ -573,12 +594,12 @@ void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref) sBoundTarget = this; } -void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo ) +void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo ) { allocate(resx,resy,color_fmt,depth,stencil,usage,use_fbo,2); } -void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo, U32 samples ) +void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples ) { stop_glerror(); mResX = resx; @@ -588,7 +609,7 @@ void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth mUseDepth = depth; mStencil = stencil; - releaseSampleBuffer(); + release(); if (!gGLManager.mHasFramebufferMultisample) { @@ -625,11 +646,9 @@ void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth { glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); } - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } - + stop_glerror(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); stop_glerror(); } @@ -668,11 +687,9 @@ void LLMultisampleBuffer::addColorAttachment(U32 color_fmt) { case GL_FRAMEBUFFER_COMPLETE_EXT: break; - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - llerrs << "WTF?" << llendl; - break; default: - llerrs << "WTF?" << llendl; + llerrs << "WTF? " << std::hex << status << llendl; + break; } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index ae8613d9be..12dd1c8b90 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -63,7 +63,7 @@ class LLRenderTarget { public: //whether or not to use FBO implementation - static BOOL sUseFBO; + static bool sUseFBO; LLRenderTarget(); virtual ~LLRenderTarget(); @@ -71,7 +71,7 @@ public: //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); + void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = FALSE); //provide this render target with a multisample resource. void setSampleBuffer(LLMultisampleBuffer* buffer); @@ -88,7 +88,7 @@ public: //free any allocated resources //safe to call redundantly - void release(); + virtual void release(); //bind target for rendering //applies appropriate viewport @@ -115,7 +115,7 @@ public: U32 getTexture(U32 attachment = 0) const; U32 getDepth(void) const { return mDepth; } - BOOL hasStencil() const { return mStencil; } + bool hasStencil() const { return mStencil; } void bindTexture(U32 index, S32 channel); @@ -125,7 +125,7 @@ public: // call bindTarget once, do all your rendering, call flush once // if fetch_depth is TRUE, every effort will be made to copy the depth buffer into // the current depth texture. A depth texture will be allocated if needed. - void flush(BOOL fetch_depth = FALSE); + void flush(bool fetch_depth = FALSE); void copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter); @@ -136,7 +136,7 @@ public: //Returns TRUE if target is ready to be rendered into. //That is, if the target has been allocated with at least //one renderable attachment (i.e. color buffer, depth buffer). - BOOL isComplete() const; + bool isComplete() const; static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; } @@ -147,9 +147,9 @@ protected: std::vector<U32> mTex; U32 mFBO; U32 mDepth; - BOOL mStencil; - BOOL mUseDepth; - BOOL mRenderDepth; + bool mStencil; + bool mUseDepth; + bool mRenderDepth; LLTexUnit::eTextureType mUsage; U32 mSamples; LLMultisampleBuffer* mSampleBuffer; @@ -164,12 +164,12 @@ public: LLMultisampleBuffer(); virtual ~LLMultisampleBuffer(); - void releaseSampleBuffer(); + virtual void release(); virtual void bindTarget(); void bindTarget(LLRenderTarget* ref); - virtual void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo); - void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo, U32 samples); + virtual void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo); + void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples); virtual void addColorAttachment(U32 color_fmt); virtual void allocateDepth(); }; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index c859d41e17..21b02fdb71 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -146,6 +146,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) return FALSE; } } + + if (features->hasObjectSkinning) + { + if (!shader->attachObject("avatar/objectSkinV.glsl")) + { + return FALSE; + } + } /////////////////////////////////////// // Attach Fragment Shader Features Next @@ -220,7 +228,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) else if (features->isFullbright) { - if (features->hasWaterFog) + if (features->isShiny && features->hasWaterFog) + { + if (!shader->attachObject("lighting/lightFullbrightShinyWaterF.glsl")) + { + return FALSE; + } + } + else if (features->hasWaterFog) { if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl")) { @@ -307,11 +322,14 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns) GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type) { - GLenum error; - error = glGetError(); - if (error != GL_NO_ERROR) + GLenum error = GL_NO_ERROR; + if (gDebugGL) { - LL_WARNS("ShaderLoading") << "GL ERROR entering loadShaderFile(): " << error << LL_ENDL; + error = glGetError(); + if (error != GL_NO_ERROR) + { + LL_WARNS("ShaderLoading") << "GL ERROR entering loadShaderFile(): " << error << LL_ENDL; + } } LL_DEBUGS("ShaderLoading") << "Loading shader file: " << filename << " class " << shader_level << LL_ENDL; @@ -366,31 +384,39 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade //create shader object GLhandleARB ret = glCreateShaderObjectARB(type); - error = glGetError(); - if (error != GL_NO_ERROR) + if (gDebugGL) { - LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShaderObjectARB: " << error << LL_ENDL; + error = glGetError(); + if (error != GL_NO_ERROR) + { + LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShaderObjectARB: " << error << LL_ENDL; + } } - else + + //load source + glShaderSourceARB(ret, count, (const GLcharARB**) text, NULL); + + if (gDebugGL) { - //load source - glShaderSourceARB(ret, count, (const GLcharARB**) text, NULL); error = glGetError(); if (error != GL_NO_ERROR) { LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSourceARB: " << error << LL_ENDL; } - else + } + + //compile source + glCompileShaderARB(ret); + + if (gDebugGL) + { + error = glGetError(); + if (error != GL_NO_ERROR) { - //compile source - glCompileShaderARB(ret); - error = glGetError(); - if (error != GL_NO_ERROR) - { - LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShaderARB: " << error << LL_ENDL; - } + LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShaderARB: " << error << LL_ENDL; } } + //free memory for (GLuint i = 0; i < count; i++) { @@ -401,13 +427,16 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade //check for errors GLint success = GL_TRUE; glGetObjectParameterivARB(ret, GL_OBJECT_COMPILE_STATUS_ARB, &success); - error = glGetError(); - if (error != GL_NO_ERROR || success == GL_FALSE) + if (gDebugGL || success == GL_FALSE) { - //an error occured, print log - LL_WARNS("ShaderLoading") << "GLSL Compilation Error: (" << error << ") in " << filename << LL_ENDL; - dumpObjectLog(ret); - ret = 0; + error = glGetError(); + if (error != GL_NO_ERROR || success == GL_FALSE) + { + //an error occured, print log + LL_WARNS("ShaderLoading") << "GLSL Compilation Error: (" << error << ") in " << filename << LL_ENDL; + dumpObjectLog(ret); + ret = 0; + } } } else diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 02160b09c4..07ec31dbd5 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -25,6 +25,7 @@ */ #include "linden_common.h" +#include "llmemory.h" #include <boost/static_assert.hpp> #include "llsys.h" @@ -33,6 +34,7 @@ #include "llglheaders.h" #include "llmemtype.h" #include "llrender.h" +#include "llvector4a.h" //============================================================================ @@ -56,20 +58,23 @@ BOOL LLVertexBuffer::sIBOActive = FALSE; U32 LLVertexBuffer::sAllocatedBytes = 0; BOOL LLVertexBuffer::sMapped = FALSE; BOOL LLVertexBuffer::sUseStreamDraw = TRUE; +S32 LLVertexBuffer::sWeight4Loc = -1; std::vector<U32> LLVertexBuffer::sDeleteList; -S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] = + +S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] = { - sizeof(LLVector3), // TYPE_VERTEX, - sizeof(LLVector3), // TYPE_NORMAL, + sizeof(LLVector4), // TYPE_VERTEX, + sizeof(LLVector4), // TYPE_NORMAL, sizeof(LLVector2), // TYPE_TEXCOORD0, sizeof(LLVector2), // TYPE_TEXCOORD1, sizeof(LLVector2), // TYPE_TEXCOORD2, sizeof(LLVector2), // TYPE_TEXCOORD3, sizeof(LLColor4U), // TYPE_COLOR, - sizeof(LLVector3), // TYPE_BINORMAL, + sizeof(LLVector4), // TYPE_BINORMAL, sizeof(F32), // TYPE_WEIGHT, + sizeof(LLVector4), // TYPE_WEIGHT4, sizeof(LLVector4), // TYPE_CLOTHWEIGHT, }; @@ -204,18 +209,37 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) glClientActiveTextureARB(GL_TEXTURE0_ARB); } + if (sLastMask & MAP_WEIGHT4) + { + if (sWeight4Loc < 0) + { + llerrs << "Weighting disabled but vertex buffer still bound!" << llendl; + } + + if (!(data_mask & MAP_WEIGHT4)) + { //disable 4-component skin weight + glDisableVertexAttribArrayARB(sWeight4Loc); + } + } + else if (data_mask & MAP_WEIGHT4) + { + if (sWeight4Loc >= 0) + { //enable 4-component skin weight + glEnableVertexAttribArrayARB(sWeight4Loc); + } + } + + sLastMask = data_mask; } } -void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const +void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const { - llassert(mRequestedNumVerts >= 0); - if (start >= (U32) mRequestedNumVerts || end >= (U32) mRequestedNumVerts) { - llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "]" << llendl; + llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "] vs " << mRequestedNumVerts << llendl; } llassert(mRequestedNumIndices >= 0); @@ -226,6 +250,25 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl; } + if (gDebugGL && !useVBOs()) + { + U16* idx = ((U16*) getIndicesPointer())+indices_offset; + for (U32 i = 0; i < count; ++i) + { + if (idx[i] < start || idx[i] > end) + { + llerrs << "Index out of range: " << idx[i] << " not in [" << start << ", " << end << "]" << llendl; + } + } + } +} + +void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const +{ + validateRange(start, end, count, indices_offset); + + llassert(mRequestedNumVerts >= 0); + if (mGLIndices != sGLRenderIndices) { llerrs << "Wrong index buffer bound." << llendl; @@ -242,9 +285,11 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi return; } + U16* idx = ((U16*) getIndicesPointer())+indices_offset; + stop_glerror(); glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, - ((U16*) getIndicesPointer()) + indices_offset); + idx); stop_glerror(); } @@ -387,17 +432,24 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : mUsage = 0; } - S32 stride = calcStride(typemask, mOffsets); + //zero out offsets + for (U32 i = 0; i < TYPE_MAX; i++) + { + mOffsets[i] = 0; + } mTypeMask = typemask; - mStride = stride; + mSize = 0; + mAlignedOffset = 0; + mAlignedIndexOffset = 0; + sCount++; } //static -S32 LLVertexBuffer::calcStride(const U32& typemask, S32* offsets) +S32 LLVertexBuffer::calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices) { - S32 stride = 0; + S32 offset = 0; for (S32 i=0; i<TYPE_MAX; i++) { U32 mask = 1<<i; @@ -405,13 +457,35 @@ S32 LLVertexBuffer::calcStride(const U32& typemask, S32* offsets) { if (offsets) { - offsets[i] = stride; + offsets[i] = offset; + offset += LLVertexBuffer::sTypeSize[i]*num_vertices; + offset = (offset + 0xF) & ~0xF; } - stride += sTypeOffsets[i]; } } - return stride; + return offset+16; +} + +//static +S32 LLVertexBuffer::calcVertexSize(const U32& typemask) +{ + S32 size = 0; + for (S32 i = 0; i < TYPE_MAX; i++) + { + U32 mask = 1<<i; + if (typemask & mask) + { + size += LLVertexBuffer::sTypeSize[i]; + } + } + + return size; +} + +S32 LLVertexBuffer::getSize() const +{ + return mSize; } // protected, use unref() @@ -523,8 +597,7 @@ void LLVertexBuffer::createGLBuffer() { static int gl_buffer_idx = 0; mGLBuffer = ++gl_buffer_idx; - mMappedData = new U8[size]; - memset(mMappedData, 0, size); + mMappedData = (U8*) malloc(size); } } @@ -545,16 +618,20 @@ void LLVertexBuffer::createGLIndices() mEmpty = TRUE; + //pad by 16 bytes for aligned copies + size += 16; + if (useVBOs()) { + //pad by another 16 bytes for VBO pointer adjustment + size += 16; mMappedIndexData = NULL; genIndices(); mResized = TRUE; } else { - mMappedIndexData = new U8[size]; - memset(mMappedIndexData, 0, size); + mMappedIndexData = (U8*) malloc(size); static int gl_buffer_idx = 0; mGLIndices = ++gl_buffer_idx; } @@ -575,7 +652,7 @@ void LLVertexBuffer::destroyGLBuffer() } else { - delete [] mMappedData; + free(mMappedData); mMappedData = NULL; mEmpty = TRUE; } @@ -584,7 +661,7 @@ void LLVertexBuffer::destroyGLBuffer() } mGLBuffer = 0; - unbind(); + //unbind(); } void LLVertexBuffer::destroyGLIndices() @@ -602,7 +679,7 @@ void LLVertexBuffer::destroyGLIndices() } else { - delete [] mMappedIndexData; + free(mMappedIndexData); mMappedIndexData = NULL; mEmpty = TRUE; } @@ -611,7 +688,7 @@ void LLVertexBuffer::destroyGLIndices() } mGLIndices = 0; - unbind(); + //unbind(); } void LLVertexBuffer::updateNumVerts(S32 nverts) @@ -627,7 +704,7 @@ void LLVertexBuffer::updateNumVerts(S32 nverts) } mRequestedNumVerts = nverts; - + if (!mDynamicSize) { mNumVerts = nverts; @@ -642,7 +719,7 @@ void LLVertexBuffer::updateNumVerts(S32 nverts) } mNumVerts = nverts; } - + mSize = calcOffsets(mTypeMask, mOffsets, mNumVerts); } void LLVertexBuffer::updateNumIndices(S32 nindices) @@ -673,6 +750,12 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) { LLMemType mt2(LLMemType::MTYPE_VERTEX_ALLOCATE_BUFFER); + if (nverts < 0 || nindices < 0 || + nverts > 65536) + { + llerrs << "Bad vertex buffer allocation: " << nverts << " : " << nindices << llendl; + } + updateNumVerts(nverts); updateNumIndices(nindices); @@ -711,9 +794,6 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) { sAllocatedBytes -= getSize() + getIndicesSize(); - S32 oldsize = getSize(); - S32 old_index_size = getIndicesSize(); - updateNumVerts(newnverts); updateNumIndices(newnindices); @@ -730,26 +810,10 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) } else { - //delete old buffer, keep GL buffer for now if (!useVBOs()) { - U8* old = mMappedData; - mMappedData = new U8[newsize]; - if (old) - { - memcpy(mMappedData, old, llmin(newsize, oldsize)); - if (newsize > oldsize) - { - memset(mMappedData+oldsize, 0, newsize-oldsize); - } - - delete [] old; - } - else - { - memset(mMappedData, 0, newsize); - mEmpty = TRUE; - } + free(mMappedData); + mMappedData = (U8*) malloc(newsize); } mResized = TRUE; } @@ -769,24 +833,8 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) { if (!useVBOs()) { - //delete old buffer, keep GL buffer for now - U8* old = mMappedIndexData; - mMappedIndexData = new U8[new_index_size]; - - if (old) - { - memcpy(mMappedIndexData, old, llmin(new_index_size, old_index_size)); - if (new_index_size > old_index_size) - { - memset(mMappedIndexData+old_index_size, 0, new_index_size - old_index_size); - } - delete [] old; - } - else - { - memset(mMappedIndexData, 0, new_index_size); - mEmpty = TRUE; - } + free(mMappedIndexData); + mMappedIndexData = (U8*) malloc(new_index_size); } mResized = TRUE; } @@ -843,12 +891,19 @@ U8* LLVertexBuffer::mapBuffer(S32 access) setBuffer(0); mLocked = TRUE; stop_glerror(); - mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + + U8* src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src); + mAlignedOffset = mMappedData - src; + stop_glerror(); } { LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES); - mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + U8* src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + mMappedIndexData = LL_NEXT_ALIGNED_ADDRESS<U8>(src); + mAlignedIndexOffset = mMappedIndexData - src; + stop_glerror(); } @@ -964,8 +1019,8 @@ template <class T,S32 type> struct VertexBufferStrider } else if (vbo.hasDataType(type)) { - S32 stride = vbo.getStride(); - strider = (T*)(vbo.getMappedData() + vbo.getOffset(type) + index*stride); + S32 stride = LLVertexBuffer::sTypeSize[type]; + strider = (T*)(vbo.getMappedData() + vbo.getOffset(type)+index*stride); strider.setStride(stride); return TRUE; } @@ -977,7 +1032,6 @@ template <class T,S32 type> struct VertexBufferStrider } }; - bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index) { return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index); @@ -1018,28 +1072,15 @@ bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index) { return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index); } -bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index) + +bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4>& strider, S32 index) { - return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index); + return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index); } -void LLVertexBuffer::setStride(S32 type, S32 new_stride) +bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index) { - LLMemType mt2(LLMemType::MTYPE_VERTEX_SET_STRIDE); - if (mNumVerts) - { - llerrs << "LLVertexBuffer::setOffset called with mNumVerts = " << mNumVerts << llendl; - } - // This code assumes that setStride() will only be called once per VBO per type. - S32 delta = new_stride - sTypeOffsets[type]; - for (S32 i=type+1; i<TYPE_MAX; i++) - { - if (mTypeMask & (1<<i)) - { - mOffsets[i] += delta; - } - } - mStride += delta; + return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index); } //---------------------------------------------------------------------------- @@ -1238,8 +1279,7 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const { LLMemType mt2(LLMemType::MTYPE_VERTEX_SETUP_VERTEX_BUFFER); stop_glerror(); - U8* base = useVBOs() ? NULL : mMappedData; - S32 stride = mStride; + U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; if ((data_mask & mTypeMask) != data_mask) { @@ -1248,52 +1288,58 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const if (data_mask & MAP_NORMAL) { - glNormalPointer(GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_NORMAL])); + glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL])); } if (data_mask & MAP_TEXCOORD3) { glClientActiveTextureARB(GL_TEXTURE3_ARB); - glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD3])); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], (void*)(base + mOffsets[TYPE_TEXCOORD3])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD2) { glClientActiveTextureARB(GL_TEXTURE2_ARB); - glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], (void*)(base + mOffsets[TYPE_TEXCOORD2])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD1) { glClientActiveTextureARB(GL_TEXTURE1_ARB); - glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD1])); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_BINORMAL) { glClientActiveTextureARB(GL_TEXTURE2_ARB); - glTexCoordPointer(3,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_BINORMAL])); + glTexCoordPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_BINORMAL], (void*)(base + mOffsets[TYPE_BINORMAL])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD0) { - glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD0])); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); } if (data_mask & MAP_COLOR) { - glColorPointer(4, GL_UNSIGNED_BYTE, stride, (void*)(base + mOffsets[TYPE_COLOR])); + glColorPointer(4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeSize[TYPE_COLOR], (void*)(base + mOffsets[TYPE_COLOR])); } if (data_mask & MAP_WEIGHT) { - glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_WEIGHT])); + glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], (void*)(base + mOffsets[TYPE_WEIGHT])); } + + if (data_mask & MAP_WEIGHT4 && sWeight4Loc != -1) + { + glVertexAttribPointerARB(sWeight4Loc, 4, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], (void*)(base+mOffsets[TYPE_WEIGHT4])); + } + if (data_mask & MAP_CLOTHWEIGHT) { - glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, stride, (void*)(base + mOffsets[TYPE_CLOTHWEIGHT])); + glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], (void*)(base + mOffsets[TYPE_CLOTHWEIGHT])); } if (data_mask & MAP_VERTEX) { - glVertexPointer(3,GL_FLOAT, stride, (void*)(base + 0)); + glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0)); } llglassertok(); diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 94fa790957..953b7e6757 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -68,16 +68,29 @@ protected: //============================================================================ -// base class +// base class class LLVertexBuffer : public LLRefCount { public: + LLVertexBuffer(const LLVertexBuffer& rhs) + { + *this = rhs; + } + + const LLVertexBuffer& operator=(const LLVertexBuffer& rhs) + { + llerrs << "Illegal operation!" << llendl; + return *this; + } + static LLVBOPool sStreamVBOPool; static LLVBOPool sDynamicVBOPool; static LLVBOPool sStreamIBOPool; static LLVBOPool sDynamicIBOPool; + static S32 sWeight4Loc; + static BOOL sUseStreamDraw; static void initClass(bool use_vbo); @@ -87,11 +100,14 @@ public: static void unbind(); //unbind any bound vertex buffer //get the size of a vertex with the given typemask - //if offsets is not NULL, its contents will be filled - //with the offset of each vertex component in the buffer, + static S32 calcVertexSize(const U32& typemask); + + //get the size of a buffer with the given typemask and vertex count + //fill offsets with the offset of each vertex component array into the buffer // indexed by the following enum - static S32 calcStride(const U32& typemask, S32* offsets = NULL); + static S32 calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices); + enum { TYPE_VERTEX, TYPE_NORMAL, @@ -103,6 +119,7 @@ public: // These use VertexAttribPointer and should possibly be made generic TYPE_BINORMAL, TYPE_WEIGHT, + TYPE_WEIGHT4, TYPE_CLOTHWEIGHT, TYPE_MAX, TYPE_INDEX, @@ -118,6 +135,7 @@ public: // These use VertexAttribPointer and should possibly be made generic MAP_BINORMAL = (1<<TYPE_BINORMAL), MAP_WEIGHT = (1<<TYPE_WEIGHT), + MAP_WEIGHT4 = (1<<TYPE_WEIGHT4), MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT), }; @@ -167,6 +185,7 @@ public: bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0); bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0); bool getWeightStrider(LLStrider<F32>& strider, S32 index=0); + bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0); bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0); BOOL isEmpty() const { return mEmpty; } @@ -176,33 +195,37 @@ public: S32 getRequestedVerts() const { return mRequestedNumVerts; } S32 getRequestedIndices() const { return mRequestedNumIndices; } - U8* getIndicesPointer() const { return useVBOs() ? NULL : mMappedIndexData; } - U8* getVerticesPointer() const { return useVBOs() ? NULL : mMappedData; } - S32 getStride() const { return mStride; } - S32 getTypeMask() const { return mTypeMask; } + U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; } + U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; } + U32 getTypeMask() const { return mTypeMask; } BOOL hasDataType(S32 type) const { return ((1 << type) & getTypeMask()) ? TRUE : FALSE; } - S32 getSize() const { return mNumVerts*mStride; } + S32 getSize() const; S32 getIndicesSize() const { return mNumIndices * sizeof(U16); } U8* getMappedData() const { return mMappedData; } U8* getMappedIndices() const { return mMappedIndexData; } S32 getOffset(S32 type) const { return mOffsets[type]; } S32 getUsage() const { return mUsage; } - void setStride(S32 type, S32 new_stride); - void markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count); void draw(U32 mode, U32 count, U32 indices_offset) const; void drawArrays(U32 mode, U32 offset, U32 count) const; void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const; + //for debugging, validate data in given range is valid + void validateRange(U32 start, U32 end, U32 count, U32 offset) const; + + + protected: S32 mNumVerts; // Number of vertices allocated S32 mNumIndices; // Number of indices allocated S32 mRequestedNumVerts; // Number of vertices requested S32 mRequestedNumIndices; // Number of indices requested - S32 mStride; + ptrdiff_t mAlignedOffset; + ptrdiff_t mAlignedIndexOffset; + S32 mSize; U32 mTypeMask; S32 mUsage; // GL usage U32 mGLBuffer; // GL VBO handle @@ -216,7 +239,7 @@ protected: S32 mOffsets[TYPE_MAX]; BOOL mResized; // if TRUE, client buffer has been resized and GL buffer has not BOOL mDynamicSize; // if TRUE, buffer has been resized at least once (and should be padded) - + class DirtyRegion { public: @@ -241,7 +264,7 @@ public: typedef std::list<LLVertexBuffer*> buffer_list_t; static BOOL sEnableVBOs; - static S32 sTypeOffsets[TYPE_MAX]; + static S32 sTypeSize[TYPE_MAX]; static U32 sGLMode[LLRender::NUM_MODES]; static U32 sGLRenderBuffer; static U32 sGLRenderIndices; |