diff options
author | Dave Parks <davep@lindenlab.com> | 2011-05-29 00:40:57 -0500 |
---|---|---|
committer | Dave Parks <davep@lindenlab.com> | 2011-05-29 00:40:57 -0500 |
commit | 1fd46831f0ea7309d83c1fa2eecc611b3bada719 (patch) | |
tree | 8e6708b1e25f12156c0a65cf6487c5f3df6c4873 | |
parent | 35c4635dca83708a09ac8f15e30aec146210fba7 (diff) |
SH-1682 Work in progress on using texture indexes to improve batch size (wow, super fast so far)
23 files changed, 398 insertions, 113 deletions
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 049dd4346b..0532510996 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -203,7 +203,9 @@ void LLTexUnit::disable(void) if (mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE && mIndex < gGLManager.mNumTextureUnits) { + stop_glerror(); glDisable(sGLTextureType[mCurrTexType]); + stop_glerror(); } mCurrTexType = TT_NONE; @@ -403,6 +405,7 @@ void LLTexUnit::unbind(eTextureType type) activate(); mCurrTexture = 0; glBindTexture(sGLTextureType[type], 0); + stop_glerror(); } } diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 8c9171ccf4..f715a8e9ba 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -1497,7 +1497,14 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const } if (data_mask & MAP_VERTEX) { - glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0)); + if (data_mask & MAP_TEXTURE_INDEX) + { + glVertexPointer(4,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0)); + } + else + { + 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 a9f22193f8..0c4b241537 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -130,6 +130,9 @@ public: TYPE_CLOTHWEIGHT, TYPE_MAX, TYPE_INDEX, + + //no actual additional data, but indicates position.w is texture index + TYPE_TEXTURE_INDEX, }; enum { MAP_VERTEX = (1<<TYPE_VERTEX), @@ -144,6 +147,7 @@ public: MAP_WEIGHT = (1<<TYPE_WEIGHT), MAP_WEIGHT4 = (1<<TYPE_WEIGHT4), MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT), + MAP_TEXTURE_INDEX = (1<<TYPE_TEXTURE_INDEX), }; protected: diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 2c6d75e3c9..22d8ce49c1 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -7489,7 +7489,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>0</integer> + <integer>1</integer> </map> <key>RenderDebugNormalScale</key> <map> diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index 35cfb80c93..f71d9f0b49 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -20,3 +20,4 @@ void main() vec3 nvn = normalize(vary_normal); gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } + diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl index 03d3322cb6..b8de629fc8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl @@ -8,13 +8,15 @@ #version 120 varying vec3 vary_normal; +varying float vary_texture_index; void main() { //transform vertex - gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz, 1.0); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + vary_texture_index = gl_Vertex.w; vary_normal = normalize(gl_NormalMatrix * gl_Normal); gl_FrontColor = gl_Color; diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl index 3429877397..30231039b0 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl @@ -9,56 +9,48 @@ #extension GL_ARB_texture_rectangle : enable -uniform sampler2D diffuseMap; -uniform sampler2DRect depthMap; -uniform sampler2D noiseMap; - -uniform vec4 shadow_clip; -uniform vec2 screen_res; +varying float vary_texture_index; + +uniform sampler2D tex0; +uniform sampler2D tex1; +uniform sampler2D tex2; +uniform sampler2D tex3; +uniform sampler2D tex4; +uniform sampler2D tex5; +uniform sampler2D tex6; +uniform sampler2D tex7; + +vec4 textureLookup(vec2 texcoord) +{ + switch (int(vary_texture_index+0.25)) + { + case 0: return texture2D(tex0, texcoord); + case 1: return texture2D(tex1, texcoord); + case 2: return texture2D(tex2, texcoord); + case 3: return texture2D(tex3, texcoord); + case 4: return texture2D(tex4, texcoord); + case 5: return texture2D(tex5, texcoord); + case 6: return texture2D(tex6, texcoord); + case 7: return texture2D(tex7, texcoord); + } + + return vec4(0,0,0,0); +} vec3 fullbrightAtmosTransport(vec3 light); vec3 fullbrightScaleSoftClip(vec3 light); -varying vec3 vary_ambient; -varying vec3 vary_directional; -varying vec4 vary_position; -varying vec3 vary_normal; -varying vec3 vary_fragcoord; - -uniform mat4 inv_proj; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} void main() { - vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; - frag *= screen_res; - - vec3 samp_pos = getPosition(frag).xyz; - float shadow = 1.0; - vec4 pos = vary_position; - vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy)*gl_Color; + vec4 color = textureLookup(gl_TexCoord[0].xy)*gl_Color; color.rgb = fullbrightAtmosTransport(color.rgb); color.rgb = fullbrightScaleSoftClip(color.rgb); - //gl_FragColor = gl_Color; gl_FragColor = color; - //gl_FragColor = vec4(1,0,1,1); - } diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl index 6c38d220e2..6890360c56 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl @@ -14,30 +14,23 @@ vec3 atmosAffectDirectionalLight(float lightIntensity); vec3 scaleDownLight(vec3 light); vec3 scaleUpLight(vec3 light); -varying vec3 vary_ambient; -varying vec3 vary_directional; -varying vec3 vary_normal; -varying vec3 vary_fragcoord; -uniform float near_clip; -varying vec4 vary_position; +varying float vary_texture_index; void main() { //transform vertex - gl_Position = ftransform(); + vec4 vert = vec4(gl_Vertex.xyz, 1.0); + vary_texture_index = gl_Vertex.w; + + gl_Position = gl_ModelViewProjectionMatrix*vert; gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - vec4 pos = (gl_ModelViewMatrix * gl_Vertex); - vary_position = pos; - + vec4 pos = (gl_ModelViewMatrix * vert); + calcAtmospherics(pos.xyz); gl_FrontColor = gl_Color; gl_FogFragCoord = pos.z; - - pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); - } diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 25e4bc847c..9645693493 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -430,14 +430,14 @@ void LLRenderPass::renderTexture(U32 type, U32 mask) pushBatches(type, mask, TRUE); } -void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture) +void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures) { for (LLCullResult::drawinfo_list_t::iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) { LLDrawInfo* pparams = *i; if (pparams) { - pushBatch(*pparams, mask, texture); + pushBatch(*pparams, mask, texture, batch_textures); } } } @@ -456,26 +456,42 @@ void LLRenderPass::applyModelMatrix(LLDrawInfo& params) } } -void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) +void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures) { applyModelMatrix(params); + bool tex_setup = false; + if (texture) { - if (params.mTexture.notNull()) + if (batch_textures && params.mTextureList.size() > 1) { - params.mTexture->addTextureStats(params.mVSize); - gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ; - if (params.mTextureMatrix) + for (U32 i = 0; i < params.mTextureList.size(); ++i) { - glMatrixMode(GL_TEXTURE); - glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); - gPipeline.mTextureMatrixOps++; + if (params.mTextureList[i].notNull()) + { + gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE); + } } } else - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + { //not batching textures or batch has only 1 texture -- might need a texture matrix + if (params.mTexture.notNull()) + { + params.mTexture->addTextureStats(params.mVSize); + gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ; + if (params.mTextureMatrix) + { + tex_setup = true; + glMatrixMode(GL_TEXTURE); + glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); + gPipeline.mTextureMatrixOps++; + } + } + else + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } } } @@ -490,7 +506,7 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); } - if (params.mTextureMatrix && texture && params.mTexture.notNull()) + if (tex_setup) { glLoadIdentity(); glMatrixMode(GL_MODELVIEW); diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index d3fd9ead0d..c7acbb42c6 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -146,8 +146,8 @@ public: void resetDrawOrders() { } static void applyModelMatrix(LLDrawInfo& params); - virtual void pushBatches(U32 type, U32 mask, BOOL texture = TRUE); - virtual void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture); + virtual void pushBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE); + virtual void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE); virtual void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE); virtual void renderGroups(U32 type, U32 mask, BOOL texture = TRUE); virtual void renderTexture(U32 type, U32 mask); diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 8b5a2ce781..3b3d48ab36 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -124,7 +124,7 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) if (pass == 0) { simple_shader = &gDeferredAlphaProgram; - fullbright_shader = &gDeferredFullbrightProgram; + fullbright_shader = &gObjectFullbrightProgram; } else { diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 5f89d11391..3531073896 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -1292,7 +1292,7 @@ void LLDrawPoolBump::renderBump(U32 type, U32 mask) } } -void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) +void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures) { applyModelMatrix(params); diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h index f4702bf61d..476b1d41b7 100644 --- a/indra/newview/lldrawpoolbump.h +++ b/indra/newview/lldrawpoolbump.h @@ -55,7 +55,7 @@ public: virtual void endRenderPass( S32 pass ); virtual S32 getNumPasses(); /*virtual*/ void prerender(); - /*virtual*/ void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture); + /*virtual*/ void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE); void renderBump(U32 type, U32 mask); void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture); diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp index 2e83167851..8ff60f73cc 100644 --- a/indra/newview/lldrawpoolsimple.cpp +++ b/indra/newview/lldrawpoolsimple.cpp @@ -44,6 +44,43 @@ static LLGLSLShader* fullbright_shader = NULL; static LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE_DEFERRED("Deferred Simple"); static LLFastTimer::DeclareTimer FTM_RENDER_GRASS_DEFERRED("Deferred Grass"); +void LLDrawPoolGlow::beginPostDeferredPass(S32 pass) +{ + gDeferredFullbrightProgram.bind(); +} + +void LLDrawPoolGlow::renderPostDeferred(S32 pass) +{ + LLFastTimer t(FTM_RENDER_GLOW); + LLGLEnable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + gGL.flush(); + /// Get rid of z-fighting with non-glow pass. + LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -1.0f); + gGL.setSceneBlendType(LLRender::BT_ADD); + + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + gGL.setColorMask(false, true); + pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + + gGL.setColorMask(true, false); + gGL.setSceneBlendType(LLRender::BT_ALPHA); +} + +void LLDrawPoolGlow::endPostDeferredPass(S32 pass) +{ + gDeferredFullbrightProgram.unbind(); + for (U32 i = 0; i < 8; i++) + { + if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE) + { + gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType()); + gGL.getTexUnit(i)->disable(); + } + } +} + void LLDrawPoolGlow::render(S32 pass) { LLFastTimer t(FTM_RENDER_GLOW); @@ -79,10 +116,10 @@ void LLDrawPoolGlow::render(S32 pass) } } -void LLDrawPoolGlow::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) +void LLDrawPoolGlow::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures) { glColor4ubv(params.mGlowColor.mV); - LLRenderPass::pushBatch(params, mask, texture); + LLRenderPass::pushBatch(params, mask, texture, batch_textures); } @@ -128,8 +165,8 @@ void LLDrawPoolSimple::endRenderPass(S32 pass) LLFastTimer t(FTM_RENDER_SIMPLE); LLRenderPass::endRenderPass(pass); - if (mVertexShaderLevel > 0){ - + if (mVertexShaderLevel > 0) + { simple_shader->unbind(); } } @@ -168,6 +205,15 @@ void LLDrawPoolSimple::endDeferredPass(S32 pass) LLRenderPass::endRenderPass(pass); gDeferredDiffuseProgram.unbind(); + + for (U32 i = 0; i < 8; i++) + { + if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE) + { + gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType()); + gGL.getTexUnit(i)->disable(); + } + } } void LLDrawPoolSimple::renderDeferred(S32 pass) @@ -177,7 +223,7 @@ void LLDrawPoolSimple::renderDeferred(S32 pass) { //render simple LLFastTimer t(FTM_RENDER_SIMPLE_DEFERRED); - renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask()); + pushBatches(LLRenderPass::PASS_SIMPLE, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); } } @@ -285,6 +331,33 @@ void LLDrawPoolFullbright::prerender() mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } +void LLDrawPoolFullbright::beginPostDeferredPass(S32 pass) +{ + gDeferredFullbrightProgram.bind(); +} + +void LLDrawPoolFullbright::renderPostDeferred(S32 pass) +{ + LLFastTimer t(FTM_RENDER_FULLBRIGHT); + + gGL.setSceneBlendType(LLRender::BT_ALPHA); + U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX; + pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE); +} + +void LLDrawPoolFullbright::endPostDeferredPass(S32 pass) +{ + gDeferredFullbrightProgram.unbind(); + for (U32 i = 0; i < 8; i++) + { + if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE) + { + gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType()); + gGL.getTexUnit(i)->disable(); + } + } +} + void LLDrawPoolFullbright::beginRenderPass(S32 pass) { LLFastTimer t(FTM_RENDER_FULLBRIGHT); diff --git a/indra/newview/lldrawpoolsimple.h b/indra/newview/lldrawpoolsimple.h index 5f3bbebbda..3811b3d398 100644 --- a/indra/newview/lldrawpoolsimple.h +++ b/indra/newview/lldrawpoolsimple.h @@ -98,9 +98,9 @@ public: LLDrawPoolFullbright(); /*virtual*/ S32 getNumPostDeferredPasses() { return 1; } - /*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); } - /*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); } - /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); } + /*virtual*/ void beginPostDeferredPass(S32 pass); + /*virtual*/ void endPostDeferredPass(S32 pass); + /*virtual*/ void renderPostDeferred(S32 pass); /*virtual*/ void beginRenderPass(S32 pass); /*virtual*/ void endRenderPass(S32 pass); @@ -126,12 +126,12 @@ public: virtual void prerender() { } /*virtual*/ S32 getNumPostDeferredPasses() { return 1; } - /*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); } - /*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); } - /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); } + /*virtual*/ void beginPostDeferredPass(S32 pass); + /*virtual*/ void endPostDeferredPass(S32 pass); + /*virtual*/ void renderPostDeferred(S32 pass); void render(S32 pass = 0); - void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture = TRUE); + void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE); }; diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 9f9e50ad0a..e30522d380 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -165,6 +165,7 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) mIndexInTex = 0; mTexture = NULL; mTEOffset = -1; + mTextureIndex = 255; setDrawable(drawablep); mVObjp = objp; @@ -386,6 +387,26 @@ void LLFace::setGeomIndex(U16 idx) } } +void LLFace::setTextureIndex(U8 index) +{ + if (index != mTextureIndex) + { + mTextureIndex = index; + + if (mTextureIndex != 255) + { + mDrawablep->setState(LLDrawable::REBUILD_POSITION); + } + else + { + if (mDrawInfo && !mDrawInfo->mTextureList.empty()) + { + llerrs << "Face with no texture index references indexed texture draw info." << llendl; + } + } + } +} + void LLFace::setIndicesIndex(S32 idx) { if (mIndicesIndex != idx) @@ -1573,6 +1594,20 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, mat_vert.affineTransform(*src++, *dst++); } while(dst < end); + + F32 index = (F32) (mTextureIndex < 255 ? mTextureIndex : 0); + F32 *index_dst = (F32*) vertices; + F32 *index_end = (F32*) end; + + index_dst += 3; + index_end += 3; + do + { + *index_dst = index; + index_dst += 4; + } + while (index_dst < index_end); + } if (rebuild_normal) diff --git a/indra/newview/llface.h b/indra/newview/llface.h index b2170c4cf3..b5eaeecd60 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -94,6 +94,8 @@ public: U16 getGeomCount() const { return mGeomCount; } // vertex count for this face U16 getGeomIndex() const { return mGeomIndex; } // index into draw pool U16 getGeomStart() const { return mGeomIndex; } // index into draw pool + void setTextureIndex(U8 index); + U8 getTextureIndex() const { return mTextureIndex; } void setTexture(LLViewerTexture* tex) ; void switchTexture(LLViewerTexture* new_texture); void dirtyTexture(); @@ -262,6 +264,7 @@ private: U16 mGeomCount; // vertex count for this face U16 mGeomIndex; // index into draw pool + U8 mTextureIndex; // index of texture channel to use for pseudo-atlasing U32 mIndicesCount; U32 mIndicesIndex; // index into draw pool for indices (yeah, I know!) S32 mIndexInTex ; diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 8143d6a41f..7f91f9a952 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -3439,6 +3439,8 @@ void renderTextureAnim(LLDrawInfo* params) void renderBatchSize(LLDrawInfo* params) { + LLGLEnable offset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.f, 1.f); glColor3ubv((GLubyte*) &(params->mDebugColor)); pushVerts(params, LLVertexBuffer::MAP_VERTEX); } @@ -3876,6 +3878,28 @@ public: renderAgentTarget(avatar); } + if (gDebugGL) + { + for (U32 i = 0; i < drawable->getNumFaces(); ++i) + { + LLFace* facep = drawable->getFace(i); + U8 index = facep->getTextureIndex(); + if (facep->mDrawInfo) + { + if (index < 255) + { + if (facep->mDrawInfo->mTextureList.size() <= index) + { + llerrs << "Face texture index out of bounds." << llendl; + } + else if (facep->mDrawInfo->mTextureList[index] != facep->getTexture()) + { + llerrs << "Face texture index incorrect." << llendl; + } + } + } + } + } } for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 0d9cad914a..ae5d4fa463 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -91,6 +91,8 @@ public: LLPointer<LLVertexBuffer> mVertexBuffer; LLPointer<LLViewerTexture> mTexture; + std::vector<LLPointer<LLViewerTexture> > mTextureList; + LLColor4U mGlowColor; S32 mDebugColor; const LLMatrix4* mTextureMatrix; @@ -684,7 +686,7 @@ class LLVolumeGeometryManager: public LLGeometryManager virtual void rebuildGeom(LLSpatialGroup* group); virtual void rebuildMesh(LLSpatialGroup* group); virtual void getGeometry(LLSpatialGroup* group); - void genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort = FALSE); + void genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE); void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type); }; diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index b818da205e..29f3acdf91 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -354,6 +354,7 @@ void LLViewerShaderMgr::setShaders() //setup preprocessor definitions LLShaderMgr::instance()->mDefinitions["samples"] = llformat("%d", gGLManager.getNumFBOFSAASamples(gSavedSettings.getU32("RenderFSAASamples"))); + LLShaderMgr::instance()->mDefinitions["NUM_TEX_UNITS"] = llformat("%d", gGLManager.mNumTextureImageUnits); reentrance = true; @@ -941,6 +942,20 @@ BOOL LLViewerShaderMgr::loadShadersEffects() } +void setup_indexed_texture(LLGLSLShader& shader) +{ + shader.bind(); + shader.uniform1i("tex0", 0); + shader.uniform1i("tex1", 1); + shader.uniform1i("tex2", 2); + shader.uniform1i("tex3", 3); + shader.uniform1i("tex4", 4); + shader.uniform1i("tex5", 5); + shader.uniform1i("tex6", 6); + shader.uniform1i("tex7", 7); + shader.unbind(); +} + BOOL LLViewerShaderMgr::loadShadersDeferred() { if (mVertexShaderLevel[SHADER_DEFERRED] == 0) @@ -992,9 +1007,14 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredDiffuseProgram.mName = "Deferred Diffuse Shader"; gDeferredDiffuseProgram.mShaderFiles.clear(); gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseIndexedF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredDiffuseProgram.createShader(NULL, NULL); + + if (success) + { //force tex0-7 to appropriate texture channels + setup_indexed_texture(gDeferredDiffuseProgram); + } } if (success) @@ -1231,6 +1251,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredFullbrightProgram.createShader(NULL, NULL); + + if (success) + { + setup_indexed_texture(gDeferredFullbrightProgram); + } } if (success) diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 6f354b78b1..85b740d819 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -418,6 +418,7 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co mFaceList.push_back(facep); vertex_count += facep->getGeomCount(); index_count += facep->getIndicesCount(); + llassert(facep->getIndicesCount() < 65536); } obj->mDepth /= count; diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index dbcd4f50ca..510525259f 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -375,6 +375,8 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, S32 num_vertices, num_indices; U32 index; + llassert(mLastStride > 0); + render_stride = mLastStride; patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); S32 vert_size = patch_size / render_stride; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index cc443d32fb..87de064ad1 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1247,17 +1247,7 @@ BOOL LLVOVolume::calcLOD() { //setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail)); - F32 bin_radius = getBinRadius(); - F32 node_size = 0.f; - - LLSpatialGroup* group = mDrawable->getSpatialGroup(); - if (group) - { - LLSpatialGroup::OctreeNode* node = group->mOctreeNode; - node_size = node->getSize()[0]; - } - - setDebugText(llformat("%.2f:%.2f", bin_radius, node_size)); + setDebugText(llformat("%d", mDrawable->getFace(0)->getTextureIndex())); } if (cur_detail != mLOD) @@ -3734,6 +3724,21 @@ LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep) mSlopRatio = 0.25f; } +bool can_batch_texture(LLFace* facep) +{ + if (facep->getTextureEntry()->getBumpmap()) + { //bump maps aren't worked into texture batching yet + return false; + } + + if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) + { //texture animation breaks batches + return false; + } + + return true; +} + void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); @@ -3784,12 +3789,36 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, LLViewerTexture* tex = facep->getTexture(); + U8 index = facep->getTextureIndex(); + + bool batchable = false; + + if (index < 255 && idx >= 0) + { + if (index < draw_vec[idx]->mTextureList.size()) + { + if (draw_vec[idx]->mTextureList[index].isNull()) + { + batchable = true; + draw_vec[idx]->mTextureList[index] = tex; + } + else if (draw_vec[idx]->mTextureList[index] == tex) + { //this face's texture index can be used with this batch + batchable = true; + } + } + else + { //texture list can be expanded to fit this texture index + batchable = true; + } + } + U8 glow = (U8) (facep->getTextureEntry()->getGlow() * 255); if (idx >= 0 && draw_vec[idx]->mVertexBuffer == facep->getVertexBuffer() && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && - (LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex) && + (LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex || batchable) && #if LL_DARWIN draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange && draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && @@ -3803,6 +3832,12 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_vec[idx]->mCount += facep->getIndicesCount(); draw_vec[idx]->mEnd += facep->getGeomCount(); draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize()); + + if (index >= draw_vec[idx]->mTextureList.size()) + { + draw_vec[idx]->mTextureList.resize(index+1); + draw_vec[idx]->mTextureList[index] = tex; + } draw_vec[idx]->validate(); update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[0]); update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[1]); @@ -3833,6 +3868,11 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_info->mDrawMode = LLRender::TRIANGLE_STRIP; } + if (index < 255) + { //initialize texture list for texture batching + draw_info->mTextureList.resize(index+1); + draw_info->mTextureList[index] = tex; + } draw_info->validate(); } } @@ -4258,11 +4298,16 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (LLPipeline::sRenderDeferred) { bump_mask |= LLVertexBuffer::MAP_BINORMAL; + genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, simple_faces, FALSE, TRUE); + genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, fullbright_faces, FALSE, TRUE); + genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, bump_faces, FALSE, TRUE); + } + else + { + genDrawInfo(group, simple_mask, simple_faces); + genDrawInfo(group, fullbright_mask, fullbright_faces); + genDrawInfo(group, bump_mask, bump_faces, FALSE, TRUE); } - - genDrawInfo(group, simple_mask, simple_faces); - genDrawInfo(group, bump_mask, bump_faces); - genDrawInfo(group, fullbright_mask, fullbright_faces); genDrawInfo(group, alpha_mask, alpha_faces, TRUE); if (!LLPipeline::sDelayVBUpdate) @@ -4376,7 +4421,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) llassert(!group || !group->isState(LLSpatialGroup::NEW_DRAWINFO)); } -void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort) +void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort, BOOL batch_textures) { //calculate maximum number of vertices to store in a single buffer U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); @@ -4435,19 +4480,71 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: std::vector<LLFace*>::iterator i = face_iter; ++i; - while (i != faces.end() && - (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) + std::vector<LLViewerTexture*> texture_list; + + if (!distance_sort && batch_textures) { - facep = *i; - - if (geom_count + facep->getGeomCount() > max_vertices) - { //cut batches on geom count too big - break; + U8 cur_tex = 0; + facep->setTextureIndex(cur_tex); + texture_list.push_back(tex); + + if (can_batch_texture(facep)) + { + while (i != faces.end()) + { + facep = *i; + if (facep->getTexture() != tex) + { + cur_tex++; + if (cur_tex >= 8) + { //cut batches on every 8 textures + break; + } + tex = facep->getTexture(); + texture_list.push_back(tex); + } + + if (geom_count + facep->getGeomCount() > max_vertices) + { //cut batches on geom count too big + break; + } + + if (!can_batch_texture(facep)) + { //cut batches on things that require single texture rendering (animated texture, bump maps) + break; + } + + ++i; + index_count += facep->getIndicesCount(); + geom_count += facep->getGeomCount(); + + facep->setTextureIndex(cur_tex); + } } - ++i; - index_count += facep->getIndicesCount(); - geom_count += facep->getGeomCount(); + tex = texture_list[0]; + } + else + { + while (i != faces.end() && + (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) + { + facep = *i; + + + //face has no texture index + facep->mDrawInfo = NULL; + facep->setTextureIndex(255); + + if (geom_count + facep->getGeomCount() > max_vertices) + { //cut batches on geom count too big + break; + } + + ++i; + index_count += facep->getIndicesCount(); + geom_count += facep->getGeomCount(); + } } //create/delete/resize vertex buffer if needed @@ -4497,6 +4594,11 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: facep->setGeomIndex(index_offset); facep->setVertexBuffer(buffer); + if (batch_textures && facep->getTextureIndex() == 255) + { + llerrs << "Invalid texture index." << llendl; + } + { //for debugging, set last time face was updated vs moved facep->updateRebuildFlags(); @@ -4695,7 +4797,7 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun { vertex_count += facep->getGeomCount(); index_count += facep->getIndicesCount(); - + llassert(facep->getIndicesCount() < 65536); //remember face (for sorting) mFaceList.push_back(facep); } |