diff options
Diffstat (limited to 'indra/llrender')
-rw-r--r-- | indra/llrender/llgl.cpp | 5 | ||||
-rw-r--r-- | indra/llrender/llgl.h | 16 | ||||
-rw-r--r-- | indra/llrender/llglslshader.cpp | 143 | ||||
-rw-r--r-- | indra/llrender/llglslshader.h | 41 | ||||
-rw-r--r-- | indra/llrender/llgltexture.cpp | 4 | ||||
-rw-r--r-- | indra/llrender/llrender.cpp | 10 | ||||
-rw-r--r-- | indra/llrender/llshadermgr.cpp | 19 | ||||
-rw-r--r-- | indra/llrender/llshadermgr.h | 14 | ||||
-rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 216 | ||||
-rw-r--r-- | indra/llrender/llvertexbuffer.h | 6 |
10 files changed, 354 insertions, 120 deletions
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 7b9d24c1e9..7959b3bb57 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -1238,6 +1238,11 @@ bool LLGLManager::initGL() glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples); glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords); glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples); + glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &mMaxUniformBlockSize); + + // sanity clamp max uniform block size to 64k just in case + // there's some implementation that reports a crazy value + mMaxUniformBlockSize = llmin(mMaxUniformBlockSize, 65536); if (mGLVersion >= 4.59f) { diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index c9130545c1..909dad2e85 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -87,6 +87,7 @@ public: S32 mGLMaxIndexRange; S32 mGLMaxTextureSize; F32 mMaxAnisotropy = 0.f; + S32 mMaxUniformBlockSize = 0; // GL 4.x capabilities bool mHasCubeMapArray = false; @@ -152,13 +153,18 @@ void assert_glerror(); void clear_glerror(); -//#if LL_DEBUG + # define stop_glerror() assert_glerror() # define llglassertok() assert_glerror() -//#else -//# define stop_glerror() -//# define llglassertok() -//#endif + +// stop_glerror is still needed on OS X but has performance implications +// use macro below to conditionally add stop_glerror to non-release builds +// on OS X +#if LL_DARWIN && !LL_RELEASE_FOR_DOWNLOAD +#define STOP_GLERROR stop_glerror() +#else +#define STOP_GLERROR +#endif #define llglassertok_always() assert_glerror() diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index f5c698e20e..e22df46b28 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -279,7 +279,7 @@ bool LLGLSLShader::readProfileQuery(bool for_runtime, bool force_read) GLuint64 samples_passed = 0; glGetQueryObjectui64v(mSamplesQuery, GL_QUERY_RESULT, &samples_passed); - U64 primitives_generated = 0; + GLuint64 primitives_generated = 0; glGetQueryObjectui64v(mPrimitivesQuery, GL_QUERY_RESULT, &primitives_generated); sTotalTimeElapsed += time_elapsed; @@ -381,10 +381,7 @@ void LLGLSLShader::unloadInternal() stop_glerror(); } -bool LLGLSLShader::createShader(std::vector<LLStaticHashedString>* attributes, - std::vector<LLStaticHashedString>* uniforms, - U32 varying_count, - const char** varyings) +bool LLGLSLShader::createShader() { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; @@ -454,11 +451,11 @@ bool LLGLSLShader::createShader(std::vector<LLStaticHashedString>* attributes, // Map attributes and uniforms if (success) { - success = mapAttributes(attributes); + success = mapAttributes(); } if (success) { - success = mapUniforms(uniforms); + success = mapUniforms(); } if (!success) { @@ -469,7 +466,7 @@ bool LLGLSLShader::createShader(std::vector<LLStaticHashedString>* attributes, { LL_SHADER_LOADING_WARNS() << "Failed to link using shader level " << mShaderLevel << " trying again using shader level " << (mShaderLevel - 1) << LL_ENDL; mShaderLevel--; - return createShader(attributes, uniforms); + return createShader(); } else { @@ -479,6 +476,7 @@ bool LLGLSLShader::createShader(std::vector<LLStaticHashedString>* attributes, } else if (mFeatures.mIndexedTextureChannels > 0) { //override texture channels for indexed texture rendering + llassert(mFeatures.mIndexedTextureChannels == LLGLSLShader::sIndexedTextureChannels); // these numbers must always match bind(); S32 channel_count = mFeatures.mIndexedTextureChannels; @@ -488,19 +486,41 @@ bool LLGLSLShader::createShader(std::vector<LLStaticHashedString>* attributes, uniform1i(uniName, i); } - S32 cur_tex = channel_count; //adjust any texture channels that might have been overwritten + //adjust any texture channels that might have been overwritten for (U32 i = 0; i < mTexture.size(); i++) { - if (mTexture[i] > -1 && mTexture[i] < channel_count) + if (mTexture[i] > -1) { - llassert(cur_tex < gGLManager.mNumTextureImageUnits); - uniform1i(i, cur_tex); - mTexture[i] = cur_tex++; + S32 new_tex = mTexture[i] + channel_count; + uniform1i(i, new_tex); + mTexture[i] = new_tex; } } + + // get the true number of active texture channels + mActiveTextureChannels = channel_count; + for (auto& tex : mTexture) + { + mActiveTextureChannels = llmax(mActiveTextureChannels, tex + 1); + } + + // when indexed texture channels are used, enforce an upper limit of 16 + // this should act as a canary in the coal mine for adding textures + // and breaking machines that are limited to 16 texture channels + llassert(mActiveTextureChannels <= 16); unbind(); } + LL_DEBUGS("GLSLTextureChannels") << mName << " has " << mActiveTextureChannels << " active texture channels" << LL_ENDL; + + for (U32 i = 0; i < mTexture.size(); i++) + { + if (mTexture[i] > -1) + { + LL_DEBUGS("GLSLTextureChannels") << "Texture " << LLShaderMgr::instance()->mReservedUniforms[i] << " assigned to channel " << mTexture[i] << LL_ENDL; + } + } + #ifdef LL_PROFILER_ENABLE_RENDER_DOC setLabel(mName.c_str()); #endif @@ -602,7 +622,7 @@ void LLGLSLShader::attachObjects(GLuint* objects, S32 count) } } -bool LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString>* attributes) +bool LLGLSLShader::mapAttributes() { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; @@ -621,11 +641,10 @@ bool LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString>* attrib } mAttribute.clear(); - U32 numAttributes = (attributes == NULL) ? 0U : static_cast<U32>(attributes->size()); #if LL_RELEASE_WITH_DEBUG_INFO - mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, { -1, NULL }); + mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size(), { -1, NULL }); #else - mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, -1); + mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size(), -1); #endif if (res) @@ -649,19 +668,6 @@ bool LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString>* attrib LL_DEBUGS("ShaderUniform") << "Attribute " << name << " assigned to channel " << index << LL_ENDL; } } - if (attributes != NULL) - { - for (U32 i = 0; i < numAttributes; i++) - { - const char* name = (*attributes)[i].String().c_str(); - S32 index = glGetAttribLocation(mProgramObject, name); - if (index != -1) - { - mAttribute[LLShaderMgr::instance()->mReservedAttribs.size() + i] = index; - LL_DEBUGS("ShaderUniform") << "Attribute " << name << " assigned to channel " << index << LL_ENDL; - } - } - } return true; } @@ -669,7 +675,7 @@ bool LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString>* attrib return false; } -void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString>* uniforms) +void LLGLSLShader::mapUniform(GLint index) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; @@ -753,22 +759,11 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString>* u //found it mUniform[i] = location; mTexture[i] = mapUniformTextureChannel(location, type, size); - return; - } - } - - if (uniforms != NULL) - { - for (U32 i = 0; i < uniforms->size(); i++) - { - if ((mUniform[i + LLShaderMgr::instance()->mReservedUniforms.size()] == -1) - && ((*uniforms)[i].String() == name)) + if (mTexture[i] != -1) { - //found it - mUniform[i + LLShaderMgr::instance()->mReservedUniforms.size()] = location; - mTexture[i + LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type, size); - return; + LL_DEBUGS("GLSLTextureChannels") << name << " assigned to texture channel " << mTexture[i] << LL_ENDL; } + return; } } } @@ -806,31 +801,27 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type, GLint if (size == 1) { glUniform1i(location, mActiveTextureChannels); - LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL; mActiveTextureChannels++; } else { //is array of textures, make sequential after this texture - GLint channel[32]; // <=== only support up to 32 texture channels - llassert(size <= 32); - size = llmin(size, 32); + GLint channel[16]; // <=== only support up to 16 texture channels + llassert(size <= 16); + size = llmin(size, 16); for (int i = 0; i < size; ++i) { channel[i] = mActiveTextureChannels++; } glUniform1iv(location, size, channel); - LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << - (mActiveTextureChannels - size) << " through " << (mActiveTextureChannels - 1) << LL_ENDL; } - llassert(mActiveTextureChannels <= 32); // too many textures (probably) return ret; } return -1; } -bool LLGLSLShader::mapUniforms(const vector<LLStaticHashedString>* uniforms) +bool LLGLSLShader::mapUniforms() { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; @@ -843,9 +834,8 @@ bool LLGLSLShader::mapUniforms(const vector<LLStaticHashedString>* uniforms) mTexture.clear(); mValue.clear(); //initialize arrays - U32 numUniforms = (uniforms == NULL) ? 0U : static_cast<U32>(uniforms->size()); - mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); - mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); + mUniform.resize(LLShaderMgr::instance()->mReservedUniforms.size(), -1); + mTexture.resize(LLShaderMgr::instance()->mReservedUniforms.size(), -1); bind(); @@ -946,26 +936,26 @@ bool LLGLSLShader::mapUniforms(const vector<LLStaticHashedString>* uniforms) if (specularDiff || bumpLessDiff || envLessDiff || refLessDiff) { - mapUniform(diffuseMap, uniforms); + mapUniform(diffuseMap); skip_index.insert(diffuseMap); if (-1 != specularMap) { - mapUniform(specularMap, uniforms); + mapUniform(specularMap); skip_index.insert(specularMap); } if (-1 != bumpMap) { - mapUniform(bumpMap, uniforms); + mapUniform(bumpMap); skip_index.insert(bumpMap); } if (-1 != environmentMap) { - mapUniform(environmentMap, uniforms); + mapUniform(environmentMap); skip_index.insert(environmentMap); } if (-1 != reflectionMap) { - mapUniform(reflectionMap, uniforms); + mapUniform(reflectionMap); skip_index.insert(reflectionMap); } } @@ -979,21 +969,29 @@ bool LLGLSLShader::mapUniforms(const vector<LLStaticHashedString>* uniforms) if (skip_index.end() != skip_index.find(i)) continue; //........................................................................................ - mapUniform(i, uniforms); + mapUniform(i); } //........................................................................................................................................ - if (mFeatures.hasReflectionProbes) // Set up block binding, in a way supported by Apple (rather than binding = 1 in .glsl). - { // See slide 35 and more of https://docs.huihoo.com/apple/wwdc/2011/session_420__advances_in_opengl_for_mac_os_x_lion.pdf - static const GLuint BLOCKBINDING = 1; //picked by us - //Get the index, similar to a uniform location - GLuint UBOBlockIndex = glGetUniformBlockIndex(mProgramObject, "ReflectionProbes"); + // Set up block binding, in a way supported by Apple (rather than binding = 1 in .glsl). + // See slide 35 and more of https://docs.huihoo.com/apple/wwdc/2011/session_420__advances_in_opengl_for_mac_os_x_lion.pdf + const char* ubo_names[] = + { + "ReflectionProbes", // UB_REFLECTION_PROBES + "GLTFJoints", // UB_GLTF_JOINTS + }; + + llassert(LL_ARRAY_SIZE(ubo_names) == NUM_UNIFORM_BLOCKS); + + for (U32 i = 0; i < NUM_UNIFORM_BLOCKS; ++i) + { + GLuint UBOBlockIndex = glGetUniformBlockIndex(mProgramObject, ubo_names[i]); if (UBOBlockIndex != GL_INVALID_INDEX) { - //Set this index to a binding index - glUniformBlockBinding(mProgramObject, UBOBlockIndex, BLOCKBINDING); + glUniformBlockBinding(mProgramObject, UBOBlockIndex, i); } } + unbind(); LL_DEBUGS("ShaderUniform") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL; @@ -1049,6 +1047,13 @@ void LLGLSLShader::bind() } } +void LLGLSLShader::bind(U8 variant) +{ + llassert(mGLTFVariants.size() == LLGLSLShader::NUM_GLTF_VARIANTS); + llassert(variant < LLGLSLShader::NUM_GLTF_VARIANTS); + mGLTFVariants[variant].bind(); +} + void LLGLSLShader::bind(bool rigged) { if (rigged) diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 3d00c311fd..cc2ba0fcff 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -44,6 +44,7 @@ public: bool hasTransport = false; // implies no lighting (it's possible to have neither though) bool hasSkinning = false; bool hasObjectSkinning = false; + bool mGLTF = false; bool hasAtmospherics = false; bool hasGamma = false; bool hasShadows = false; @@ -51,7 +52,6 @@ public: bool hasSrgb = false; bool isDeferred = false; bool hasScreenSpaceReflections = false; - bool disableTextureIndex = false; bool hasAlphaMask = false; bool hasReflectionProbes = false; bool attachNothing = false; @@ -145,6 +145,14 @@ public: SG_COUNT } eGroup; + enum UniformBlock : GLuint + { + UB_REFLECTION_PROBES, + UB_GLTF_JOINTS, + NUM_UNIFORM_BLOCKS + }; + + static std::set<LLGLSLShader*> sInstances; static bool sProfileEnabled; @@ -175,17 +183,14 @@ public: // If force_read is true, will force an immediate readback (severe performance penalty) bool readProfileQuery(bool for_runtime = false, bool force_read = false); - bool createShader(std::vector<LLStaticHashedString>* attributes, - std::vector<LLStaticHashedString>* uniforms, - U32 varying_count = 0, - const char** varyings = NULL); + bool createShader(); bool attachFragmentObject(std::string object); bool attachVertexObject(std::string object); void attachObject(GLuint object); void attachObjects(GLuint* objects = NULL, S32 count = 0); - bool mapAttributes(const std::vector<LLStaticHashedString>* attributes); - bool mapUniforms(const std::vector<LLStaticHashedString>*); - void mapUniform(GLint index, const std::vector<LLStaticHashedString>*); + bool mapAttributes(); + bool mapUniforms(); + void mapUniform(GLint index); void uniform1i(U32 index, GLint i); void uniform1f(U32 index, GLfloat v); void fastUniform1f(U32 index, GLfloat v); @@ -318,6 +323,26 @@ public: // this pointer should be set to whichever shader represents this shader's rigged variant LLGLSLShader* mRiggedVariant = nullptr; + // variants for use by GLTF renderer + // bit 0 = alpha mode blend (1) or opaque (0) + // bit 1 = rigged (1) or static (0) + // bit 2 = unlit (1) or lit (0) + // bit 3 = single (0) or multi (1) uv coordinates + struct GLTFVariant + { + constexpr static U8 ALPHA_BLEND = 1; + constexpr static U8 RIGGED = 2; + constexpr static U8 UNLIT = 4; + constexpr static U8 MULTI_UV = 8; + }; + + constexpr static U8 NUM_GLTF_VARIANTS = 16; + + std::vector<LLGLSLShader> mGLTFVariants; + + //helper to bind GLTF variant + void bind(U8 variant); + // hacky flag used for optimization in LLDrawPoolAlpha bool mCanBindFast = false; diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp index df2f636d05..e614f45986 100644 --- a/indra/llrender/llgltexture.cpp +++ b/indra/llrender/llgltexture.cpp @@ -49,8 +49,8 @@ LLGLTexture::LLGLTexture(const LLImageRaw* raw, bool usemipmaps) mUseMipMaps = usemipmaps ; // Create an empty image of the specified size and width mGLTexturep = new LLImageGL(raw, usemipmaps) ; - mFullWidth = mGLTexturep->getCurrentWidth(); - mFullHeight = mGLTexturep->getCurrentHeight(); + mFullWidth = mGLTexturep->getWidth(); + mFullHeight = mGLTexturep->getHeight(); mComponents = mGLTexturep->getComponents(); setTexelsPerImage(); } diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 399281be84..cfefde3acc 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -990,6 +990,7 @@ void LLRender::syncLightState() void LLRender::syncMatrices() { + STOP_GLERROR; static const U32 name[] = { LLShaderMgr::MODELVIEW_MATRIX, @@ -1012,8 +1013,6 @@ void LLRender::syncMatrices() if (shader) { - //llassert(shader); - bool mvp_done = false; U32 i = MM_MODELVIEW; @@ -1134,6 +1133,7 @@ void LLRender::syncMatrices() syncLightState(); } } + STOP_GLERROR; } void LLRender::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z) @@ -1585,6 +1585,7 @@ void LLRender::end() } void LLRender::flush() { + STOP_GLERROR; if (mCount > 0) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; @@ -1685,7 +1686,7 @@ void LLRender::flush() if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0) { - vb->setTexCoordData(mTexcoordsp.get()); + vb->setTexCoord0Data(mTexcoordsp.get()); } if (attribute_mask & LLVertexBuffer::MAP_COLOR) @@ -1693,6 +1694,9 @@ void LLRender::flush() vb->setColorData(mColorsp.get()); } +#if LL_DARWIN + vb->unmapBuffer(); +#endif vb->unbind(); sVBCache[vhash] = { vb , std::chrono::steady_clock::now() }; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 56b863466a..574cf55a0e 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -295,7 +295,7 @@ bool LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) if (features->hasLighting) { - if (features->disableTextureIndex) + if (features->mIndexedTextureChannels <= 1) { if (features->hasAlphaMask) { @@ -1157,6 +1157,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedAttribs.push_back("weight"); mReservedAttribs.push_back("weight4"); mReservedAttribs.push_back("clothing"); + mReservedAttribs.push_back("joint"); mReservedAttribs.push_back("texture_index"); //matrix state @@ -1177,9 +1178,17 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("texture_base_color_transform"); // (GLTF) mReservedUniforms.push_back("texture_normal_transform"); // (GLTF) mReservedUniforms.push_back("texture_metallic_roughness_transform"); // (GLTF) + mReservedUniforms.push_back("texture_occlusion_transform"); // (GLTF) mReservedUniforms.push_back("texture_emissive_transform"); // (GLTF) + mReservedUniforms.push_back("base_color_texcoord"); // (GLTF) + mReservedUniforms.push_back("emissive_texcoord"); // (GLTF) + mReservedUniforms.push_back("normal_texcoord"); // (GLTF) + mReservedUniforms.push_back("metallic_roughness_texcoord"); // (GLTF) + mReservedUniforms.push_back("occlusion_texcoord"); // (GLTF) - llassert(mReservedUniforms.size() == LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM+1); + mReservedUniforms.push_back("terrain_texture_transforms"); // (GLTF) + + llassert(mReservedUniforms.size() == LLShaderMgr::TERRAIN_TEXTURE_TRANSFORMS +1); mReservedUniforms.push_back("viewport"); @@ -1223,6 +1232,9 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("diffuseMap"); mReservedUniforms.push_back("altDiffuseMap"); mReservedUniforms.push_back("specularMap"); + mReservedUniforms.push_back("metallicRoughnessMap"); + mReservedUniforms.push_back("normalMap"); + mReservedUniforms.push_back("occlusionMap"); mReservedUniforms.push_back("emissiveMap"); mReservedUniforms.push_back("bumpMap"); mReservedUniforms.push_back("bumpMap2"); @@ -1234,7 +1246,6 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("heroProbes"); mReservedUniforms.push_back("cloud_noise_texture"); mReservedUniforms.push_back("cloud_noise_texture_next"); - mReservedUniforms.push_back("fullbright"); mReservedUniforms.push_back("lightnorm"); mReservedUniforms.push_back("sunlight_color"); mReservedUniforms.push_back("ambient_color"); @@ -1346,7 +1357,6 @@ void LLShaderMgr::initAttribsAndUniforms() llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW5+1); - mReservedUniforms.push_back("normalMap"); mReservedUniforms.push_back("positionMap"); mReservedUniforms.push_back("diffuseRect"); mReservedUniforms.push_back("specularRect"); @@ -1359,7 +1369,6 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("bloomMap"); mReservedUniforms.push_back("projectionMap"); mReservedUniforms.push_back("norm_mat"); - mReservedUniforms.push_back("texture_gamma"); mReservedUniforms.push_back("specular_color"); mReservedUniforms.push_back("env_intensity"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index c94e4e9acb..c00aff3a9a 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -56,7 +56,15 @@ public: TEXTURE_BASE_COLOR_TRANSFORM, // "texture_base_color_transform" (GLTF) TEXTURE_NORMAL_TRANSFORM, // "texture_normal_transform" (GLTF) TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, // "texture_metallic_roughness_transform" (GLTF) + TEXTURE_OCCLUSION_TRANSFORM, // "texture_occlusion_transform" (GLTF) TEXTURE_EMISSIVE_TRANSFORM, // "texture_emissive_transform" (GLTF) + BASE_COLOR_TEXCOORD, // "base_color_texcoord" (GLTF) + EMISSIVE_TEXCOORD, // "emissive_texcoord" (GLTF) + NORMAL_TEXCOORD, // "normal_texcoord" (GLTF) + METALLIC_ROUGHNESS_TEXCOORD, // "metallic_roughness_texcoord" (GLTF) + OCCLUSION_TEXCOORD, // "occlusion_texcoord" (GLTF) + + TERRAIN_TEXTURE_TRANSFORMS, // "terrain_texture_transforms" (GLTF) VIEWPORT, // "viewport" LIGHT_POSITION, // "light_position" @@ -91,6 +99,9 @@ public: DIFFUSE_MAP, // "diffuseMap" ALTERNATE_DIFFUSE_MAP, // "altDiffuseMap" SPECULAR_MAP, // "specularMap" + METALLIC_ROUGHNESS_MAP, // "metallicRoughnessMap" + NORMAL_MAP, // "normalMap" + OCCLUSION_MAP, // "occlusionMap" EMISSIVE_MAP, // "emissiveMap" BUMP_MAP, // "bumpMap" BUMP_MAP2, // "bumpMap2" @@ -102,7 +113,6 @@ public: HERO_PROBE, // "heroProbes" CLOUD_NOISE_MAP, // "cloud_noise_texture" CLOUD_NOISE_MAP_NEXT, // "cloud_noise_texture_next" - FULLBRIGHT, // "fullbright" LIGHTNORM, // "lightnorm" SUNLIGHT_COLOR, // "sunlight_color" AMBIENT, // "ambient_color" @@ -200,7 +210,6 @@ public: DEFERRED_SHADOW3, // "shadowMap3" DEFERRED_SHADOW4, // "shadowMap4" DEFERRED_SHADOW5, // "shadowMap5" - DEFERRED_NORMAL, // "normalMap" DEFERRED_POSITION, // "positionMap" DEFERRED_DIFFUSE, // "diffuseRect" DEFERRED_SPECULAR, // "specularRect" @@ -213,7 +222,6 @@ public: DEFERRED_BLOOM, // "bloomMap" DEFERRED_PROJECTION, // "projectionMap" DEFERRED_NORM_MATRIX, // "norm_mat" - TEXTURE_GAMMA, // "texture_gamma" SPECULAR_COLOR, // "specular_color" ENVIRONMENT_INTENSITY, // "env_intensity" diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 1580e76ed6..f82ec30242 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -290,6 +290,62 @@ static GLuint gen_buffer() #define ANALYZE_VBO_POOL 0 +#if LL_DARWIN + +// experimental -- disable VBO pooling on OS X and use glMapBuffer +class LLVBOPool +{ +public: + U64 mAllocated = 0; + + U64 getVramBytesUsed() + { + return mAllocated; + } + + void allocate(GLenum type, U32 size, GLuint& name, U8*& data) + { + 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 + llassert(size >= 2); // any buffer size smaller than a single index is nonsensical + + mAllocated += size; + + { //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; + } + } + + void free(GLenum type, U32 size, GLuint name, U8* data) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; + llassert(type == GL_ARRAY_BUFFER || type == GL_ELEMENT_ARRAY_BUFFER); + llassert(size >= 2); + + if (data) + { + ll_aligned_free_16(data); + } + + mAllocated -= size; + STOP_GLERROR; + if (name) + { + glDeleteBuffers(1, &name); + } + STOP_GLERROR; + } +}; + +#else + class LLVBOPool { public: @@ -509,9 +565,8 @@ public: mIBOPool.clear(); mVBOPool.clear(); } - - }; +#endif static LLVBOPool* sVBOPool = nullptr; @@ -545,6 +600,7 @@ const U32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] = sizeof(F32), // TYPE_WEIGHT, sizeof(LLVector4), // TYPE_WEIGHT4, sizeof(LLVector4), // TYPE_CLOTHWEIGHT, + sizeof(U64), // TYPE_JOINT, sizeof(LLVector4), // TYPE_TEXTURE_INDEX (actually exists as position.w), no extra data, but stride is 16 bytes }; @@ -562,6 +618,7 @@ static const std::string vb_type_name[] = "TYPE_WEIGHT", "TYPE_WEIGHT4", "TYPE_CLOTHWEIGHT", + "TYPE_JOINT" "TYPE_TEXTURE_INDEX", "TYPE_MAX", "TYPE_INDEX", @@ -629,6 +686,8 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; llassert(LLGLSLShader::sCurBoundShaderPtr != NULL); + STOP_GLERROR; + gGL.syncMatrices(); U32 mask = LLVertexBuffer::MAP_VERTEX; @@ -685,6 +744,7 @@ bool LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of } { +#if 0 // not a reliable test for VBOs that are not backed by a CPU buffer U16* idx = (U16*) mMappedIndexData+indices_offset; for (U32 i = 0; i < count; ++i) { @@ -722,6 +782,7 @@ bool LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of } } } +#endif } return true; @@ -739,8 +800,10 @@ 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::draw(U32 mode, U32 count, U32 indices_offset) const @@ -756,7 +819,9 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const llassert(mGLIndices == sGLRenderIndices); gGL.syncMatrices(); + STOP_GLERROR; glDrawArrays(sGLMode[mode], first, count); + STOP_GLERROR; } //static @@ -779,9 +844,10 @@ 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; } @@ -1034,8 +1100,7 @@ bool LLVertexBuffer::updateNumIndices(U32 nindices) bool LLVertexBuffer::allocateBuffer(U32 nverts, U32 nindices) { - if (nverts < 0 || nindices < 0 || - nverts > 65536) + if (nverts < 0 || nindices < 0) { LL_ERRS() << "Bad vertex buffer allocation: " << nverts << " : " << nindices << LL_ENDL; } @@ -1078,6 +1143,7 @@ U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 inde count = mNumVerts - index; } +#if !LL_DARWIN U32 start = mOffsets[type] + sTypeSize[type] * index; U32 end = start + sTypeSize[type] * count-1; @@ -1098,7 +1164,7 @@ U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 inde //didn't expand an existing region, make a new one mMappedVertexRegions.push_back({ start, end }); } - +#endif return mMappedData+mOffsets[type]+sTypeSize[type]*index; } @@ -1112,6 +1178,7 @@ U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count) count = mNumIndices-index; } +#if !LL_DARWIN U32 start = sizeof(U16) * index; U32 end = start + sizeof(U16) * count-1; @@ -1132,6 +1199,7 @@ U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count) //didn't expand an existing region, make a new one mMappedIndexRegions.push_back({ start, end }); } +#endif return mMappedIndexData + sizeof(U16)*index; } @@ -1140,9 +1208,17 @@ U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count) // target -- "target" parameter for glBufferSubData // start -- first byte to copy // end -- last byte to copy (NOT last byte + 1) -// data -- mMappedData or mMappedIndexData -static void flush_vbo(GLenum target, U32 start, U32 end, void* data) -{ +// data -- data to be flushed +// dst -- mMappedData or mMappedIndexData +static void flush_vbo(GLenum target, U32 start, U32 end, void* data, U8* dst) +{ +#if LL_DARWIN + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb memcpy"); + STOP_GLERROR; + // copy into mapped buffer + memcpy(dst+start, data, end-start+1); +#else + // skip mapped data and stream to GPU via glBufferSubData if (end != 0) { LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("glBufferSubData"); @@ -1161,10 +1237,12 @@ static void flush_vbo(GLenum target, U32 start, U32 end, void* data) glBufferSubData(target, i, size, (U8*) data + (i-start)); } } +#endif } void LLVertexBuffer::unmapBuffer() { + STOP_GLERROR; struct SortMappedRegion { bool operator()(const MappedRegion& lhs, const MappedRegion& rhs) @@ -1173,9 +1251,51 @@ void LLVertexBuffer::unmapBuffer() } }; +#if LL_DARWIN + STOP_GLERROR; + if (mMappedData) + { + if (mGLBuffer) + { + glDeleteBuffers(1, &mGLBuffer); + } + mGLBuffer = gen_buffer(); + glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); + sGLRenderBuffer = mGLBuffer; + glBufferData(GL_ARRAY_BUFFER, mSize, mMappedData, GL_STATIC_DRAW); + } + else if (mGLBuffer != sGLRenderBuffer) + { + glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); + sGLRenderBuffer = mGLBuffer; + } + STOP_GLERROR; + + if (mMappedIndexData) + { + if (mGLIndices) + { + glDeleteBuffers(1, &mGLIndices); + } + + mGLIndices = gen_buffer(); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); + sGLRenderIndices = mGLIndices; + + glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndicesSize, mMappedIndexData, GL_STATIC_DRAW); + } + else if (mGLIndices != sGLRenderIndices) + { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); + sGLRenderIndices = mGLIndices; + } + STOP_GLERROR; +#else + if (!mMappedVertexRegions.empty()) { LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - vertex"); + if (sGLRenderBuffer != mGLBuffer) { glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); @@ -1196,14 +1316,13 @@ void LLVertexBuffer::unmapBuffer() } else { - flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start); + flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start, mMappedData); start = region.mStart; end = region.mEnd; } } - flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start); - + flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start, mMappedData); mMappedVertexRegions.clear(); } @@ -1230,16 +1349,16 @@ void LLVertexBuffer::unmapBuffer() } else { - flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start); + flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start, mMappedIndexData); start = region.mStart; end = region.mEnd; } } - flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start); - + flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start, mMappedIndexData); mMappedIndexRegions.clear(); } +#endif } //---------------------------------------------------------------------------- @@ -1360,6 +1479,13 @@ bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, U32 in // Set for rendering void LLVertexBuffer::setBuffer() { + STOP_GLERROR; +#if LL_DARWIN + if (!mGLBuffer) + { // OS X doesn't allocate a buffer until we call unmapBuffer + return; + } +#endif // no data may be pending llassert(mMappedVertexRegions.empty()); llassert(mMappedIndexRegions.empty()); @@ -1392,12 +1518,15 @@ void LLVertexBuffer::setBuffer() glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); sGLRenderIndices = mGLIndices; } + + STOP_GLERROR; } // virtual (default) void LLVertexBuffer::setupVertexBuffer() { + STOP_GLERROR; U8* base = nullptr; U32 data_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask; @@ -1469,6 +1598,12 @@ void LLVertexBuffer::setupVertexBuffer() void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT4]); glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr); } + if (data_mask & MAP_JOINT) + { + AttributeType loc = TYPE_JOINT; + void* ptr = (void*)(base + mOffsets[TYPE_JOINT]); + glVertexAttribIPointer(loc, 4, GL_UNSIGNED_SHORT, LLVertexBuffer::sTypeSize[TYPE_JOINT], ptr); + } if (data_mask & MAP_CLOTHWEIGHT) { AttributeType loc = TYPE_CLOTHWEIGHT; @@ -1487,59 +1622,92 @@ void LLVertexBuffer::setupVertexBuffer() void* 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) { +#if !LL_DARWIN + llassert(sGLRenderBuffer == mGLBuffer); +#endif + flush_vbo(GL_ARRAY_BUFFER, 0, sizeof(LLVector4a) * getNumVerts()-1, (U8*) data, mMappedData); +} + +void LLVertexBuffer::setTexCoord0Data(const LLVector2* data) +{ +#if !LL_DARWIN llassert(sGLRenderBuffer == mGLBuffer); - flush_vbo(GL_ARRAY_BUFFER, 0, sizeof(LLVector4a) * getNumVerts()-1, (U8*) data); +#endif + flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TEXCOORD0], mOffsets[TYPE_TEXCOORD0] + sTypeSize[TYPE_TEXCOORD0] * getNumVerts() - 1, (U8*)data, mMappedData); } -void LLVertexBuffer::setTexCoordData(const LLVector2* data) +void LLVertexBuffer::setTexCoord1Data(const LLVector2* data) { +#if !LL_DARWIN llassert(sGLRenderBuffer == mGLBuffer); - flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TEXCOORD0], mOffsets[TYPE_TEXCOORD0] + sTypeSize[TYPE_TEXCOORD0] * getNumVerts() - 1, (U8*)data); +#endif + flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TEXCOORD1], mOffsets[TYPE_TEXCOORD1] + sTypeSize[TYPE_TEXCOORD1] * getNumVerts() - 1, (U8*)data, mMappedData); } void LLVertexBuffer::setColorData(const LLColor4U* data) { +#if !LL_DARWIN llassert(sGLRenderBuffer == mGLBuffer); - flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_COLOR], mOffsets[TYPE_COLOR] + sTypeSize[TYPE_COLOR] * getNumVerts() - 1, (U8*) data); +#endif + flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_COLOR], mOffsets[TYPE_COLOR] + sTypeSize[TYPE_COLOR] * getNumVerts() - 1, (U8*) data, mMappedData); } void LLVertexBuffer::setNormalData(const LLVector4a* data) { +#if !LL_DARWIN llassert(sGLRenderBuffer == mGLBuffer); - flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_NORMAL], mOffsets[TYPE_NORMAL] + sTypeSize[TYPE_NORMAL] * getNumVerts() - 1, (U8*) data); +#endif + flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_NORMAL], mOffsets[TYPE_NORMAL] + sTypeSize[TYPE_NORMAL] * getNumVerts() - 1, (U8*) data, mMappedData); } void LLVertexBuffer::setTangentData(const LLVector4a* data) { +#if !LL_DARWIN llassert(sGLRenderBuffer == mGLBuffer); - flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TANGENT], mOffsets[TYPE_TANGENT] + sTypeSize[TYPE_TANGENT] * getNumVerts() - 1, (U8*) data); +#endif + flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TANGENT], mOffsets[TYPE_TANGENT] + sTypeSize[TYPE_TANGENT] * getNumVerts() - 1, (U8*) data, mMappedData); } void LLVertexBuffer::setWeight4Data(const LLVector4a* data) { +#if !LL_DARWIN llassert(sGLRenderBuffer == mGLBuffer); - flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_WEIGHT4], mOffsets[TYPE_WEIGHT4] + sTypeSize[TYPE_WEIGHT4] * getNumVerts() - 1, (U8*) data); +#endif + flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_WEIGHT4], mOffsets[TYPE_WEIGHT4] + sTypeSize[TYPE_WEIGHT4] * getNumVerts() - 1, (U8*) data, mMappedData); +} + +void LLVertexBuffer::setJointData(const U64* data) +{ +#if !LL_DARWIN + llassert(sGLRenderBuffer == mGLBuffer); +#endif + flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_JOINT], mOffsets[TYPE_JOINT] + sTypeSize[TYPE_JOINT] * getNumVerts() - 1, (U8*) data, mMappedData); } void LLVertexBuffer::setIndexData(const U16* data) { +#if !LL_DARWIN llassert(sGLRenderIndices == mGLIndices); - flush_vbo(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(U16) * getNumIndices() - 1, (U8*) data); +#endif + flush_vbo(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(U16) * getNumIndices() - 1, (U8*) data, mMappedIndexData); } void LLVertexBuffer::setIndexData(const U32* data) { +#if !LL_DARWIN llassert(sGLRenderIndices == mGLIndices); +#endif if (mIndicesType != GL_UNSIGNED_INT) { // HACK -- vertex buffers are initialized as 16-bit indices, but can be switched to 32-bit indices mIndicesType = GL_UNSIGNED_INT; mIndicesStride = 4; mNumIndices /= 2; } - flush_vbo(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(U32) * getNumIndices() - 1, (U8*)data); + flush_vbo(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(U32) * getNumIndices() - 1, (U8*)data, mMappedIndexData); } diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index f75849c82f..601096abf9 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -110,6 +110,7 @@ public: TYPE_WEIGHT, // "weight" TYPE_WEIGHT4, // "weight4" TYPE_CLOTHWEIGHT, // "clothing" + TYPE_JOINT, // "joint" TYPE_TEXTURE_INDEX, // "texture_index" TYPE_MAX, // TYPE_MAX is the size/boundary marker for attributes that go in the vertex buffer TYPE_INDEX, // TYPE_INDEX is beyond _MAX because it lives in a separate (index) buffer @@ -129,6 +130,7 @@ public: MAP_WEIGHT = (1<<TYPE_WEIGHT), MAP_WEIGHT4 = (1<<TYPE_WEIGHT4), MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT), + MAP_JOINT = (1<<TYPE_JOINT), MAP_TEXTURE_INDEX = (1<<TYPE_TEXTURE_INDEX), }; @@ -193,7 +195,9 @@ public: void setNormalData(const LLVector4a* data); void setTangentData(const LLVector4a* data); void setWeight4Data(const LLVector4a* data); - void setTexCoordData(const LLVector2* data); + void setJointData(const U64* data); + void setTexCoord0Data(const LLVector2* data); + void setTexCoord1Data(const LLVector2* data); void setColorData(const LLColor4U* data); void setIndexData(const U16* data); void setIndexData(const U32* data); |