diff options
Diffstat (limited to 'indra/llrender')
| -rw-r--r-- | indra/llrender/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/llrender/llcubemap.cpp | 2 | ||||
| -rw-r--r-- | indra/llrender/llcubemaparray.cpp | 5 | ||||
| -rw-r--r-- | indra/llrender/llfontfreetype.cpp | 12 | ||||
| -rw-r--r-- | indra/llrender/llfontfreetypesvg.cpp | 12 | ||||
| -rw-r--r-- | indra/llrender/llfontfreetypesvg.h | 6 | ||||
| -rw-r--r-- | indra/llrender/llgl.cpp | 52 | ||||
| -rw-r--r-- | indra/llrender/llgl.h | 24 | ||||
| -rw-r--r-- | indra/llrender/llglheaders.h | 13 | ||||
| -rw-r--r-- | indra/llrender/llglslshader.cpp | 53 | ||||
| -rw-r--r-- | indra/llrender/llimagegl.cpp | 199 | ||||
| -rw-r--r-- | indra/llrender/llrender.cpp | 109 | ||||
| -rw-r--r-- | indra/llrender/llrender.h | 14 | ||||
| -rw-r--r-- | indra/llrender/llrender2dutils.cpp | 2 | ||||
| -rw-r--r-- | indra/llrender/llrendertarget.cpp | 193 | ||||
| -rw-r--r-- | indra/llrender/llrendertarget.h | 11 | ||||
| -rw-r--r-- | indra/llrender/llshadermgr.cpp | 18 | ||||
| -rw-r--r-- | indra/llrender/llshadermgr.h | 14 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 150 |
19 files changed, 715 insertions, 176 deletions
diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index 82ffa5dde4..35209da9a9 100644 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -112,6 +112,8 @@ target_link_libraries(llrender endif() +include(LibraryInstall) + if (USE_PRECOMPILED_HEADERS) target_precompile_headers(llrender REUSE_FROM llprecompiled) endif () diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index b15cec5804..c52f68d298 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -220,7 +220,9 @@ void LLCubeMap::initEnvironmentMap(const std::vector<LLPointer<LLImageRaw> >& ra enableTexture(0); bind(); mImages[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); +#if GL_VERSION_3_2 glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); +#endif glGenerateMipmap(GL_TEXTURE_CUBE_MAP); gGL.getTexUnit(0)->disable(); disable(); diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp index 998b57217d..e0a8782c33 100644 --- a/indra/llrender/llcubemaparray.cpp +++ b/indra/llrender/llcubemaparray.cpp @@ -114,6 +114,8 @@ LLCubeMapArray::LLCubeMapArray(LLCubeMapArray& lhs, U32 width, U32 count) : mTex allocate(mWidth, lhs.mImage->getComponents(), count, lhs.mImage->getUseMipMaps(), lhs.mHDR); // Copy each cubemap from the incoming array to the new array + // The call to glTexSubImage3D causes an INVALID OPERATION OpenGL error. For now we comment this.. + /* U32 min_count = std::min(count, lhs.mCount); for (U32 i = 0; i < min_count * 6; ++i) { @@ -133,6 +135,7 @@ LLCubeMapArray::LLCubeMapArray(LLCubeMapArray& lhs, U32 width, U32 count) : mTex glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, i, mWidth, mWidth, 1, components, GL_UNSIGNED_BYTE, scaled_image->getData()); } } + */ } LLCubeMapArray::~LLCubeMapArray() @@ -168,8 +171,10 @@ void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, bool us U32 mip_resolution = resolution; while (mip_resolution >= 1) { +#if GL_VERSION_4_0 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, format, mip_resolution, mip_resolution, count * 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); +#endif if (!use_mips) { diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index bd4df8983c..ab3089a269 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -32,7 +32,7 @@ // Freetype stuff #include <ft2build.h> #ifdef LL_WINDOWS -#include <freetype2\freetype\ftsystem.h> +#include <freetype/ftsystem.h> #endif #include "llfontfreetypesvg.h" @@ -54,7 +54,9 @@ #include "llgl.h" #include "llwindow.h" -#define ENABLE_OT_SVG_SUPPORT +#if !defined(LL_NO_OTSVG) + #define ENABLE_OT_SVG_SUPPORT +#endif FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL; @@ -89,7 +91,7 @@ LLFontManager::LLFontManager() FT_Done_FreeType(gFTLibrary); } -#ifdef ENABLE_OT_SVG_SUPPORT +#if defined(ENABLE_OT_SVG_SUPPORT) SVG_RendererHooks hooks = { LLFontFreeTypeSvgRenderer::OnInit, LLFontFreeTypeSvgRenderer::OnFree, @@ -503,8 +505,8 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch, EFontGlyphType glyph_type continue; } glyph_index = FT_Get_Char_Index(pair.first->mFTFace, wch); - if (glyph_index) - { + if (glyph_index) + { return addGlyphFromFont(pair.first, wch, glyph_index, glyph_type); } diff --git a/indra/llrender/llfontfreetypesvg.cpp b/indra/llrender/llfontfreetypesvg.cpp index 71f751329e..04825ae8a3 100644 --- a/indra/llrender/llfontfreetypesvg.cpp +++ b/indra/llrender/llfontfreetypesvg.cpp @@ -34,9 +34,17 @@ #endif #define NANOSVG_IMPLEMENTATION +#if __FreeBSD__ +#include <nanosvg.h> +#else #include <nanosvg/nanosvg.h> +#endif #define NANOSVGRAST_IMPLEMENTATION +#if __FreeBSD__ +#include <nanosvgrast.h> +#else #include <nanosvg/nanosvgrast.h> +#endif #if LL_WINDOWS #pragma warning (pop) @@ -80,6 +88,7 @@ void LLFontFreeTypeSvgRenderer::OnDataFinalizer(void* objectp) //static FT_Error LLFontFreeTypeSvgRenderer::OnPresetGlypthSlot(FT_GlyphSlot glyph_slot, FT_Bool cache, FT_Pointer*) { +#ifndef LL_NO_OTSVG FT_SVG_Document document = static_cast<FT_SVG_Document>(glyph_slot->other); llassert(!glyph_slot->generic.data || !cache || glyph_slot->glyph_index == ((LLSvgRenderData*)glyph_slot->generic.data)->GlyphIndex); @@ -166,6 +175,9 @@ FT_Error LLFontFreeTypeSvgRenderer::OnPresetGlypthSlot(FT_GlyphSlot glyph_slot, } return FT_Err_Ok; +#else + return FT_Err_Unimplemented_Feature; +#endif } // static diff --git a/indra/llrender/llfontfreetypesvg.h b/indra/llrender/llfontfreetypesvg.h index 4170cab273..94b83d5fff 100644 --- a/indra/llrender/llfontfreetypesvg.h +++ b/indra/llrender/llfontfreetypesvg.h @@ -29,7 +29,11 @@ #include <ft2build.h> #include FT_TYPES_H #include FT_MODULE_H -#include FT_OTSVG_H +#ifdef FT_OTSVG_H + #include FT_OTSVG_H +#else + #define LL_NO_OTSVG +#endif // See https://freetype.org/freetype2/docs/reference/ft2-svg_fonts.html class LLFontFreeTypeSvgRenderer diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 8545f634a3..f5ffa43b30 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -81,7 +81,7 @@ static const std::string HEADLESS_VERSION_STRING("1.0"); llofstream gFailLog; -#if GL_ARB_debug_output +#if GL_ARB_debug_output || GL_KHR_debug #ifndef APIENTRY #define APIENTRY @@ -104,9 +104,9 @@ void APIENTRY gl_debug_callback(GLenum source, }*/ if (gGLManager.mIsDisabled && - severity == GL_DEBUG_SEVERITY_HIGH_ARB && - source == GL_DEBUG_SOURCE_API_ARB && - type == GL_DEBUG_TYPE_ERROR_ARB && + severity == GL_DEBUG_SEVERITY_HIGH && + source == GL_DEBUG_SOURCE_API && + type == GL_DEBUG_TYPE_ERROR && id == GL_INVALID_VALUE) { // Suppress messages about deleting already deleted objects called from LLViewerWindow::stopGL() @@ -166,7 +166,11 @@ void APIENTRY gl_debug_callback(GLenum source, if (ubo != 0) { glGetBufferParameteriv(GL_UNIFORM_BUFFER, GL_BUFFER_SIZE, &ubo_size); +#if GL_EXT_buffer_storage + glGetBufferParameteriv(GL_UNIFORM_BUFFER, GL_BUFFER_IMMUTABLE_STORAGE_EXT, &ubo_immutable); +#else glGetBufferParameteriv(GL_UNIFORM_BUFFER, GL_BUFFER_IMMUTABLE_STORAGE, &ubo_immutable); +#endif } // No needs to halt when is called from LLViewerWindow::stopGL() @@ -245,7 +249,7 @@ PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = nullptr; PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT = nullptr; #endif -#if LL_LINUX && LL_X11 && !LL_MESA_HEADLESS +#if (LL_LINUX || __FreeBSD__) && LL_X11 && !LL_MESA_HEADLESS // GLX_MESA_query_renderer PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC glXQueryCurrentRendererIntegerMESA = nullptr; PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC glXQueryCurrentRendererStringMESA = nullptr; @@ -253,7 +257,7 @@ PFNGLXQUERYRENDERERINTEGERMESAPROC glXQueryRendererIntegerMESA = nullptr; PFNGLXQUERYRENDERERSTRINGMESAPROC glXQueryRendererStringMESA = nullptr; #endif -#if LL_LINUX && LL_WAYLAND &&!LL_MESA_HEADLESS +#if (LL_LINUX || __FreeBSD__) && LL_WAYLAND &&!LL_MESA_HEADLESS // EGL_VERSION_1_0 PFNEGLQUERYSTRINGPROC eglQueryString = nullptr; #endif @@ -1047,7 +1051,7 @@ void LLGLManager::initWGL() void LLGLManager::initGLX() { -#if LL_LINUX && LL_X11 && !LL_MESA_HEADLESS +#if (LL_LINUX || __FreeBSD__) && LL_X11 && !LL_MESA_HEADLESS if (!mIsX11) return; @@ -1066,7 +1070,7 @@ void LLGLManager::initGLX() void LLGLManager::initEGL() { -#if LL_LINUX && LL_WAYLAND && !LL_MESA_HEADLESS +#if (LL_LINUX || __FreeBSD__) && LL_WAYLAND && !LL_MESA_HEADLESS if (!mIsWayland) return; @@ -1179,6 +1183,7 @@ bool LLGLManager::initGL() parse_glsl_version(mGLSLVersionMajor, mGLSLVersionMinor); } +#if GL_VERSION_1_3 if (mGLVersion >= 2.1f && LLImageGL::sCompressTextures) { //use texture compression glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST); @@ -1187,12 +1192,13 @@ bool LLGLManager::initGL() { //GL version is < 3.0, always disable texture compression LLImageGL::sCompressTextures = false; } +#endif // Trailing space necessary to keep "nVidia Corpor_ati_on" cards // from being recognized as ATI. // NOTE: AMD has been pretty good about not breaking this check, do not rename without good reason if (mGLVendor.substr(0,4) == "ATI " -#if LL_LINUX +#if LL_LINUX || __FreeBSD__ || mGLVendor.find("AMD") != std::string::npos #endif //LL_LINUX ) @@ -1207,7 +1213,7 @@ bool LLGLManager::initGL() mIsNVIDIA = true; } else if (mGLVendor.find("INTEL") != std::string::npos -#if LL_LINUX +#if LL_LINUX || __FreeBSD__ // The Mesa-based drivers put this in the Renderer string, // not the Vendor string. || mGLRenderer.find("INTEL") != std::string::npos @@ -1264,7 +1270,7 @@ bool LLGLManager::initGL() } else #endif -#if LL_LINUX && LL_X11 && !LL_MESA_HEADLESS +#if (LL_LINUX || __FreeBSD__) && LL_X11 && !LL_MESA_HEADLESS if(mHasGLXMESAQueryRenderer && mVRAM == 0) { unsigned int vram_val = 0; @@ -1280,7 +1286,7 @@ bool LLGLManager::initGL() } #endif -#if LL_WINDOWS || LL_LINUX +#if LL_WINDOWS || LL_LINUX || __FreeBSD__ { if (mHasNVXGpuMemoryInfo && mVRAM == 0) { @@ -1312,10 +1318,12 @@ bool LLGLManager::initGL() } glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mNumTextureImageUnits); +#if GL_VERSION_3_2 glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &mMaxColorTextureSamples); glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &mMaxDepthTextureSamples); glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples); glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords); +#endif glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples); glGetIntegerv(GL_MAX_VARYING_VECTORS, &mMaxVaryingVectors); glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &mMaxUniformBlockSize); @@ -1329,7 +1337,7 @@ bool LLGLManager::initGL() if (mHasAnisotropic) { - glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &mMaxAnisotropy); + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &mMaxAnisotropy); } initGLStates(); @@ -1523,7 +1531,7 @@ void LLGLManager::reloadExtensionsString() } #endif -#if LL_SDL_WINDOW && LL_LINUX && LL_X11 && !LL_MESA_HEADLESS +#if LL_SDL_WINDOW && (LL_LINUX || __FreeBSD__) && LL_X11 && !LL_MESA_HEADLESS if (mIsX11) { if (LLWindowSDL::sX11Data.xdisplay && LLWindowSDL::sX11Data.xwindow) @@ -1544,7 +1552,7 @@ void LLGLManager::reloadExtensionsString() } #endif -#if LL_SDL_WINDOW && LL_LINUX && LL_WAYLAND && !LL_MESA_HEADLESS +#if LL_SDL_WINDOW && (LL_LINUX || __FreeBSD__) && LL_WAYLAND && !LL_MESA_HEADLESS if (mIsWayland) { SDL_EGLDisplay egl_display = SDL_EGL_GetCurrentDisplay(); @@ -2303,6 +2311,7 @@ void rotate_quat(LLQuaternion& rotation) void flush_glerror() { + if(!gDebugGL) return; glGetError(); } @@ -2340,8 +2349,10 @@ const std::string getGLErrorString(GLenum error) } //this function outputs gl error to the log file, does not crash the code. -void log_glerror() +void log_glerror(std::string comment) { + if(!gDebugGL) return; + if (LL_UNLIKELY(!gGLManager.mInited)) { return ; @@ -2349,7 +2360,7 @@ void log_glerror() // Create or update texture to be used with this data GLenum error; error = glGetError(); - while (LL_UNLIKELY(error)) + if (error != GL_NO_ERROR) { std::string gl_error_msg = getGLErrorString(error); LL_WARNS() << "GL Error: 0x" << std::hex << error << std::dec << " GL Error String: " << gl_error_msg << LL_ENDL; @@ -2414,6 +2425,7 @@ void assert_glerror() void clear_glerror() { + if(!gDebugGL) return; glGetError(); glGetError(); } @@ -2437,8 +2449,10 @@ void LLGLState::initClass() // sStateMap[GL_TEXTURE_2D] = GL_TRUE; //make sure multisample defaults to disabled +#if GL_EXT_multisample || GL_EXT_multisampled_compatibility sStateMap[GL_MULTISAMPLE] = GL_FALSE; glDisable(GL_MULTISAMPLE); +#endif } //static @@ -2453,6 +2467,7 @@ void LLGLState::restoreGL() void LLGLState::resetTextureStates() { gGL.flush(); +#if GL_VERSION_1_3 GLint maxTextureUnits; glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits); @@ -2461,6 +2476,7 @@ void LLGLState::resetTextureStates() gGL.getTexUnit(j)->activate(); j == 0 ? gGL.getTexUnit(j)->enable(LLTexUnit::TT_TEXTURE) : gGL.getTexUnit(j)->disable(); } +#endif } void LLGLState::dumpStates() @@ -2989,5 +3005,3 @@ extern "C" __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; } #endif - - diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 469802657a..83ba8f2f26 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -150,7 +150,7 @@ public: // GL Extension String std::set<std::string> mGLExtensions; -#if LL_LINUX +#if LL_LINUX || __FreeBSD__ bool mIsX11 = false; bool mIsWayland = false; #endif @@ -170,24 +170,26 @@ void rotate_quat(LLQuaternion& rotation); void flush_glerror(); // Flush GL errors when we know we're handling them correctly. -void log_glerror(); +void log_glerror(std::string comment); void assert_glerror(); void clear_glerror(); -# define stop_glerror() assert_glerror() -# define llglassertok() assert_glerror() - -// 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() +//#if !LL_RELEASE_FOR_DOWNLOAD +#if 0 +# define LOG_GLERROR(COMMENT) log_glerror(COMMENT) +# define stop_glerror() log_glerror("stop") +# define llglassertok() log_glerror("ASSERTOK") +# define STOP_GLERROR log_glerror("STOP") #else -#define STOP_GLERROR +# define LOG_GLERROR(COMMENT) +# define stop_glerror() +# define llglassertok() +# define STOP_GLERROR #endif + #define llglassertok_always() assert_glerror() //////////////////////// diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index a3d63810f5..a805f19154 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -27,7 +27,7 @@ #ifndef LL_LLGLHEADERS_H #define LL_LLGLHEADERS_H -#if LL_WINDOWS || LL_MESA_HEADLESS || LL_SDL_WINDOW || LL_LINUX +#if LL_WINDOWS || LL_MESA_HEADLESS || LL_SDL_WINDOW || LL_LINUX || __FreeBSD__ //---------------------------------------------------------------------------- // LL_WINDOWS || LL_MESA_HEADLESS || LL_SDL_WINDOW || LL_LINUX @@ -42,19 +42,20 @@ // quotes so we get libraries/.../GL/ version #include "GL/glcorearb.h" +#include "GL/glext.h" #if LL_WINDOWS && !LL_MESA_HEADLESS #include "GL/wglext.h" #endif -#if LL_LINUX && LL_X11 && !LL_MESA_HEADLESS +#if (LL_LINUX || __FreeBSD__) && LL_X11 && !LL_MESA_HEADLESS #define GLX_GLXEXT_LEGACY #define __gl_h_ 1 #include "GL/glx.h" #include "GL/glxext.h" #endif -#if LL_LINUX && LL_WAYLAND && !LL_MESA_HEADLESS +#if (LL_LINUX || __FreeBSD__) && LL_WAYLAND && !LL_MESA_HEADLESS #define EGL_EGL_PROTOTYPES 0 #include "EGL/egl.h" #endif @@ -68,7 +69,7 @@ #define GL_EXT_separate_specular_color 1 #define GL_GLEXT_PROTOTYPES 1 -#include "GL/glext.h" +#include <OpenGL/glext.h> #endif // LL_MESA_HEADLESS / LL_SDL_WINDOW // LL_LINUX / LL_WINDOWS / LL_DARWIN @@ -165,7 +166,7 @@ extern PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB; #endif // LL_WINDOWS -#if LL_LINUX && LL_X11 && !LL_MESA_HEADLESS +#if (LL_LINUX || __FreeBSD__) && LL_X11 && !LL_MESA_HEADLESS // GLX_MESA_query_renderer extern PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC glXQueryCurrentRendererIntegerMESA; extern PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC glXQueryCurrentRendererStringMESA; @@ -173,7 +174,7 @@ extern PFNGLXQUERYRENDERERINTEGERMESAPROC glXQueryRendererIntegerMESA; extern PFNGLXQUERYRENDERERSTRINGMESAPROC glXQueryRendererStringMESA; #endif -#if LL_LINUX && LL_WAYLAND &&!LL_MESA_HEADLESS +#if (LL_LINUX || __FreeBSD__) && LL_WAYLAND &&!LL_MESA_HEADLESS extern PFNEGLQUERYSTRINGPROC eglQueryString; #endif diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index a268ea07bb..7ec23f5da0 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -256,12 +256,18 @@ void LLGLSLShader::placeProfileQuery(bool for_runtime) glGenQueries(1, &mPrimitivesQuery); } - glBeginQuery(GL_TIME_ELAPSED, mTimerQuery); +#if GL_EXT_timer_query || GL_EXT_disjoint_timer_query + glBeginQuery(GL_TIME_ELAPSED_EXT, mTimerQuery); +#endif if (!for_runtime) { +#if GL_VERSION_1_5 glBeginQuery(GL_SAMPLES_PASSED, mSamplesQuery); +#endif +#if GL_VERSION_3_0 glBeginQuery(GL_PRIMITIVES_GENERATED, mPrimitivesQuery); +#endif } } } @@ -272,19 +278,30 @@ bool LLGLSLShader::readProfileQuery(bool for_runtime, bool force_read) { if (!mProfilePending) { - glEndQuery(GL_TIME_ELAPSED); +#if GL_EXT_timer_query || GL_EXT_disjoint_timer_query + glEndQuery(GL_TIME_ELAPSED_EXT); +#endif if (!for_runtime) { +#if GL_VERSION_1_5 glEndQuery(GL_SAMPLES_PASSED); +#endif +#if GL_VERSION_3_0 glEndQuery(GL_PRIMITIVES_GENERATED); +#endif } mProfilePending = for_runtime; } if (mProfilePending && for_runtime && !force_read) { +#if GL_ARB_timer_query GLuint64 result = 0; glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT_AVAILABLE, &result); +#else + GLuint result = 0; + glGetQueryObjectuiv(mTimerQuery, GL_QUERY_RESULT_AVAILABLE, &result); +#endif if (result != GL_TRUE) { @@ -292,22 +309,34 @@ bool LLGLSLShader::readProfileQuery(bool for_runtime, bool force_read) } } +#if GL_ARB_timer_query GLuint64 time_elapsed = 0; glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT, &time_elapsed); +#else + GLuint time_elapsed = 0; + glGetQueryObjectuiv(mTimerQuery, GL_QUERY_RESULT, &time_elapsed); +#endif mTimeElapsed += time_elapsed; mProfilePending = false; if (!for_runtime) { +#if GL_ARB_timer_query GLuint64 samples_passed = 0; glGetQueryObjectui64v(mSamplesQuery, GL_QUERY_RESULT, &samples_passed); GLuint64 primitives_generated = 0; glGetQueryObjectui64v(mPrimitivesQuery, GL_QUERY_RESULT, &primitives_generated); +#else + GLuint primitives_generated = 0; + glGetQueryObjectuiv(mPrimitivesQuery, GL_QUERY_RESULT, &primitives_generated); +#endif sTotalTimeElapsed += time_elapsed; +#if GL_VERSION_1_5 sTotalSamplesDrawn += samples_passed; mSamplesDrawn += samples_passed; +#endif U32 tri_count = (U32)primitives_generated / 3; @@ -725,10 +754,14 @@ void LLGLSLShader::mapUniform(GLint index) case GL_FLOAT_VEC2: size *= 2; break; case GL_FLOAT_VEC3: size *= 3; break; case GL_FLOAT_VEC4: size *= 4; break; +#if GL_VERSION_1_1 case GL_DOUBLE: size *= 2; break; +#if GL_VERSION_4_0 case GL_DOUBLE_VEC2: size *= 2; break; case GL_DOUBLE_VEC3: size *= 6; break; case GL_DOUBLE_VEC4: size *= 8; break; +#endif // GL_VERSION_4_0 +#endif // GL_VERSION_1_1 case GL_INT_VEC2: size *= 2; break; case GL_INT_VEC3: size *= 3; break; case GL_INT_VEC4: size *= 4; break; @@ -747,6 +780,7 @@ void LLGLSLShader::mapUniform(GLint index) case GL_FLOAT_MAT3x4: size *= 12; break; case GL_FLOAT_MAT4x2: size *= 8; break; case GL_FLOAT_MAT4x3: size *= 12; break; +#if GL_VERSION_4_0 case GL_DOUBLE_MAT2: size *= 8; break; case GL_DOUBLE_MAT3: size *= 18; break; case GL_DOUBLE_MAT4: size *= 32; break; @@ -756,6 +790,7 @@ void LLGLSLShader::mapUniform(GLint index) case GL_DOUBLE_MAT3x4: size *= 24; break; case GL_DOUBLE_MAT4x2: size *= 16; break; case GL_DOUBLE_MAT4x3: size *= 24; break; +#endif // GL_VERSION_4_0 } mTotalUniformSize += size; } @@ -819,7 +854,10 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type, GLint { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - if ((type >= GL_SAMPLER_1D && type <= GL_SAMPLER_2D_RECT_SHADOW) || + if ( +#if GL_VERSION_2_0 + (type >= GL_SAMPLER_1D && type <= GL_SAMPLER_2D_RECT_SHADOW) || +#endif type == GL_SAMPLER_2D_MULTISAMPLE || type == GL_SAMPLER_CUBE_MAP_ARRAY) { //this here is a texture @@ -1060,7 +1098,14 @@ void LLGLSLShader::bind() { sCurBoundShaderPtr->readProfileQuery(); } - LLVertexBuffer::unbind(); + // Apple's OpenGL-on-Metal layer pays a high price for rebinding buffer + // objects on every shader transition. LLVertexBuffer tracks the + // attribute formats needed by the new shader, so the current buffer + // can remain bound until a draw actually selects a different one. + if (!gGLManager.mIsApple) + { + LLVertexBuffer::unbind(); + } glUseProgram(mProgramObject); sCurBoundShader = mProgramObject; sCurBoundShaderPtr = this; diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 81743713a1..b01c81fc28 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -300,30 +300,48 @@ S32 LLImageGL::dataFormatBits(S32 dataformat) { switch (dataformat) { +#if GL_VERSION_3_0 case GL_COMPRESSED_RED: return 8; case GL_COMPRESSED_RG: return 16; +#endif +#if GL_VERSION_1_3 case GL_COMPRESSED_RGB: return 24; +#endif +#if GL_VERSION_2_1 case GL_COMPRESSED_SRGB: return 32; +#endif +#if GL_VERSION_1_3 case GL_COMPRESSED_RGBA: return 32; +#endif +#if GL_VERSION_2_1 case GL_COMPRESSED_SRGB_ALPHA: return 32; +#endif +#if GL_VERSION_1_3 case GL_COMPRESSED_LUMINANCE: return 8; case GL_COMPRESSED_LUMINANCE_ALPHA: return 16; case GL_COMPRESSED_ALPHA: return 8; +#endif +#if GL_EXT_texture_compression_s3tc || GL_EXT_texture_compression_dxt1 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return 4; - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 4; case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return 8; - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 8; case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return 8; +#endif +#if GL_EXT_texture_sRGB || GL_EXT_texture_compression_s3tc_srgb + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 4; + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 8; case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 8; +#endif case GL_LUMINANCE: return 8; - case GL_LUMINANCE8: return 8; case GL_ALPHA: return 8; - case GL_ALPHA8: return 8; case GL_RED: return 8; case GL_R8: return 8; +#if GL_VERSION_1_1 + case GL_LUMINANCE8: return 8; + case GL_ALPHA8: return 8; case GL_COLOR_INDEX: return 8; - case GL_LUMINANCE_ALPHA: return 16; case GL_LUMINANCE8_ALPHA8: return 16; +#endif + case GL_LUMINANCE_ALPHA: return 16; case GL_RG: return 16; case GL_RG8: return 16; case GL_RGB: return 24; @@ -333,10 +351,14 @@ S32 LLImageGL::dataFormatBits(S32 dataformat) case GL_RGBA: return 32; case GL_RGBA8: return 32; case GL_RGB10_A2: return 32; +#if GL_VERSION_2_1 case GL_SRGB_ALPHA: return 32; case GL_BGRA: return 32; // Used for QuickTime media textures on the Mac +#endif case GL_DEPTH_COMPONENT: return 24; + case GL_DEPTH_COMPONENT16: return 16; case GL_DEPTH_COMPONENT24: return 24; + case GL_DEPTH_COMPONENT32: return 32; case GL_RGBA16: return 64; case GL_R16F: return 16; case GL_RG16F: return 32; @@ -357,6 +379,8 @@ S64 LLImageGL::dataFormatBytes(S32 dataformat, S32 width, S32 height) { switch (dataformat) { +#if GL_EXT_texture_compression_s3tc || GL_EXT_texture_compression_dxt1 \ + || GL_EXT_texture_sRGB || GL_EXT_texture_compression_s3tc_srgb case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: @@ -366,6 +390,7 @@ S64 LLImageGL::dataFormatBytes(S32 dataformat, S32 width, S32 height) if (width < 4) width = 4; if (height < 4) height = 4; break; +#endif default: break; } @@ -379,23 +404,31 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat) { switch (dataformat) { +#if GL_EXT_texture_compression_s3tc || GL_EXT_texture_compression_dxt1 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return 3; - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 3; case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return 4; - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 4; case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return 4; +#endif +#if GL_EXT_texture_sRGB || GL_EXT_texture_compression_s3tc_srgb + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 3; + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 4; case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 4; +#endif case GL_LUMINANCE: return 1; case GL_ALPHA: return 1; case GL_RED: return 1; +#if GL_VERSION_1_1 case GL_COLOR_INDEX: return 1; +#endif case GL_LUMINANCE_ALPHA: return 2; case GL_RG: return 2; case GL_RGB: return 3; case GL_SRGB: return 3; case GL_RGBA: return 4; +#if GL_VERSION_2_1 case GL_SRGB_ALPHA: return 4; case GL_BGRA: return 4; // Used for QuickTime media textures on the Mac +#endif default: LL_ERRS() << "LLImageGL::Unknown format: " << std::hex << dataformat << std::dec << LL_ENDL; return 0; @@ -409,6 +442,8 @@ void LLImageGL::updateStats(F32 current_time) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; sLastFrameTime = current_time; + sBindCount = 0; + sUniqueCount = 0; } //---------------------------------------------------------------------------- @@ -796,11 +831,13 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 } else { +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); stop_glerror(); } +#endif LLImageGL::setManualImage(mTarget, gl_level, mFormatInternal, w, h, mFormatPrimary, GL_UNSIGNED_BYTE, (GLvoid*)data_in, mAllowCompression); if (gl_level == 0) @@ -809,11 +846,13 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 } updatePickMask(w, h, data_in); +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); stop_glerror(); } +#endif stop_glerror(); } @@ -826,11 +865,13 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 { stop_glerror(); { +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); stop_glerror(); } +#endif S32 w = getWidth(mCurrentDiscardLevel); S32 h = getHeight(mCurrentDiscardLevel); @@ -846,11 +887,13 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 updatePickMask(w, h, data_in); +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); stop_glerror(); } +#endif { LL_PROFILE_GPU_ZONE("generate mip map"); @@ -934,11 +977,13 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 llassert(w > 0 && h > 0 && cur_mip_data); (void)cur_mip_data; { +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); stop_glerror(); } +#endif LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data, mAllowCompression); if (m == 0) @@ -951,11 +996,13 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 updatePickMask(w, h, cur_mip_data); } +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); stop_glerror(); } +#endif } if (prev_mip_data && prev_mip_data != data_in) { @@ -990,11 +1037,13 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 } else { +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); stop_glerror(); } +#endif LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h, mFormatPrimary, mFormatType, (GLvoid *)data_in, mAllowCompression); @@ -1004,11 +1053,13 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 stop_glerror(); +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); stop_glerror(); } +#endif } } @@ -1024,7 +1075,9 @@ U32 type_width_from_pixtype(U32 pixtype) { case GL_UNSIGNED_BYTE: case GL_BYTE: +#if GL_VERSION_1_2 case GL_UNSIGNED_INT_8_8_8_8_REV: +#endif type_width = 1; break; case GL_UNSIGNED_SHORT: @@ -1179,11 +1232,13 @@ bool LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 glPixelStorei(GL_UNPACK_ROW_LENGTH, data_width); stop_glerror(); +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); stop_glerror(); } +#endif const U8* sub_datap = datap + (y_pos * data_width + x_pos) * getComponents(); // Update the GL texture @@ -1207,11 +1262,13 @@ bool LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 gGL.getTexUnit(0)->disable(); stop_glerror(); +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); stop_glerror(); } +#endif glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); stop_glerror(); @@ -1233,7 +1290,7 @@ bool LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_ { glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height); mGLTextureCreated = true; - stop_glerror(); + LOG_GLERROR("LLImageGL::setSubImageFromFrameBuffer()"); return true; } else @@ -1316,24 +1373,30 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt { if (pixformat == GL_ALPHA) { //GL_ALPHA is deprecated, convert to RGBA +#if GL_VERSION_3_3 const GLint mask[] = { GL_ZERO, GL_ZERO, GL_ZERO, GL_RED }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, mask); +#endif pixformat = GL_RED; intformat = GL_R8; } if (pixformat == GL_LUMINANCE) { //GL_LUMINANCE is deprecated, convert to GL_RGBA +#if GL_VERSION_3_3 const GLint mask[] = { GL_RED, GL_RED, GL_RED, GL_ONE }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, mask); +#endif pixformat = GL_RED; intformat = GL_R8; } if (pixformat == GL_LUMINANCE_ALPHA) { //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA +#if GL_VERSION_3_3 const GLint mask[] = { GL_RED, GL_RED, GL_RED, GL_GREEN }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, mask); +#endif pixformat = GL_RG; intformat = GL_RG8; } @@ -1410,39 +1473,63 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt { case GL_RED: case GL_R8: +#if GL_VERSION_3_0 intformat = GL_COMPRESSED_RED; +#endif break; case GL_RG: case GL_RG8: +#if GL_VERSION_3_0 intformat = GL_COMPRESSED_RG; +#endif break; case GL_RGB: case GL_RGB8: +#if GL_VERSION_1_3 intformat = GL_COMPRESSED_RGB; +#endif break; case GL_SRGB: case GL_SRGB8: +#if GL_VERSION_2_1 intformat = GL_COMPRESSED_SRGB; +#endif break; case GL_RGBA: case GL_RGBA8: +#if GL_VERSION_1_3 intformat = GL_COMPRESSED_RGBA; +#endif break; - case GL_SRGB_ALPHA: case GL_SRGB8_ALPHA8: +#if GL_VERSION_2_1 + case GL_SRGB_ALPHA: intformat = GL_COMPRESSED_SRGB_ALPHA; +#endif break; case GL_LUMINANCE: +#if GL_VERSION_1_1 case GL_LUMINANCE8: +#endif +#if GL_VERSION_1_3 intformat = GL_COMPRESSED_LUMINANCE; +#endif break; case GL_LUMINANCE_ALPHA: +#if GL_VERSION_1_1 case GL_LUMINANCE8_ALPHA8: +#endif +#if GL_VERSION_1_3 intformat = GL_COMPRESSED_LUMINANCE_ALPHA; +#endif break; case GL_ALPHA: +#if GL_VERSION_1_1 case GL_ALPHA8: +#endif +#if GL_VERSION_1_3 intformat = GL_COMPRESSED_ALPHA; +#endif break; default: LL_WARNS() << "Could not compress format: " << std::hex << intformat << std::dec << LL_ENDL; @@ -1577,13 +1664,21 @@ bool LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S { case 1: // Use luminance alpha (for fonts) +#if GL_VERSION_1_1 mFormatInternal = GL_LUMINANCE8; +#else + mFormatInternal = GL_LUMINANCE; +#endif mFormatPrimary = GL_LUMINANCE; mFormatType = GL_UNSIGNED_BYTE; break; case 2: // Use luminance alpha (for fonts) +#if GL_VERSION_1_1 mFormatInternal = GL_LUMINANCE8_ALPHA8; +#else + mFormatInternal = GL_LUMINANCE_ALPHA; +#endif mFormatPrimary = GL_LUMINANCE_ALPHA; mFormatType = GL_UNSIGNED_BYTE; break; @@ -1744,32 +1839,58 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name) // wait for texture upload to finish before notifying main thread // upload is complete auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); - glFlush(); - glClientWaitSync(sync, 0, GL_TIMEOUT_IGNORED); - glDeleteSync(sync); + if (sync) + { + glFlush(); + glClientWaitSync(sync, 0, GL_TIMEOUT_IGNORED); + glDeleteSync(sync); + } + else + { + glFinish(); + } } else { // post a sync to the main thread (will execute before tex name swap lambda below) // glFlush calls here are partly superstitious and partly backed by observation // on AMD hardware - glFlush(); - auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); - glFlush(); - LL::WorkQueue::postMaybe( - mMainQueue, - [=]() + if (gGLManager.mIsApple) + { + // Apple's GL/Metal translator faults in GLDFenceRec::getStatus + // (null fence, address 0x24) while executing glWaitSync. + // glFenceSync and glFinish both enqueue that wait. Flush the + // upload onto the serial OpenGL queue and let the main thread + // issue later commands behind it. + glFlush(); + } + else + { + glFlush(); + auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + glFlush(); + if (sync) { - LL_PROFILE_ZONE_NAMED("cglt - wait sync"); - { - LL_PROFILE_ZONE_NAMED("glWaitSync"); - glWaitSync(sync, 0, GL_TIMEOUT_IGNORED); - } - { - LL_PROFILE_ZONE_NAMED("glDeleteSync"); - glDeleteSync(sync); - } - }); + LL::WorkQueue::postMaybe( + mMainQueue, + [=]() + { + LL_PROFILE_ZONE_NAMED("cglt - wait sync"); + { + LL_PROFILE_ZONE_NAMED("glWaitSync"); + glWaitSync(sync, 0, GL_TIMEOUT_IGNORED); + } + { + LL_PROFILE_ZONE_NAMED("glDeleteSync"); + glDeleteSync(sync); + } + }); + } + else + { + glFinish(); + } + } } } @@ -1866,6 +1987,7 @@ bool LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre LLImageDataLock lock(imageraw); +#if GL_VERSION_1_3 if (is_compressed) { LLGLint glbytes; @@ -1911,6 +2033,7 @@ bool LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre glGetTexImage(GL_TEXTURE_2D, gl_discard, mFormatPrimary, mFormatType, (GLvoid*)(imageraw->getData())); //stop_glerror(); } +#endif // GL_VERSION_1_3 //----------------------------------------------------------------------------------------------- if((error = glGetError()) != GL_NO_ERROR) @@ -2002,11 +2125,13 @@ bool LLImageGL::getIsResident(bool test_now) { if (test_now) { +#if GL_VERSION_1_1 if (mTexName != 0) { mIsResident = true; } else +#endif { mIsResident = false; } @@ -2139,7 +2264,9 @@ void LLImageGL::calcAlphaChannelOffsetAndStride() mIsMask = false; return; //no alpha channel. case GL_RGBA: +#if GL_VERSION_2_1 case GL_SRGB_ALPHA: +#endif mAlphaStride = 4; break; case GL_BGRA: @@ -2154,6 +2281,7 @@ void LLImageGL::calcAlphaChannelOffsetAndStride() { mAlphaOffset = mAlphaStride - 1 ; } +#if GL_VERSION_1_2 else if(is_little_endian()) { if (mFormatType == GL_UNSIGNED_INT_8_8_8_8) @@ -2176,6 +2304,7 @@ void LLImageGL::calcAlphaChannelOffsetAndStride() mAlphaOffset = 0 ; } } +#endif // GL_VERSION_1_2 if( mAlphaStride < 1 || //unsupported format mAlphaOffset < 0 || //unsupported type @@ -2420,6 +2549,8 @@ bool LLImageGL::isCompressed() bool is_compressed = false; switch (mFormatPrimary) { +#if GL_EXT_texture_compression_s3tc || GL_EXT_texture_compression_dxt1 \ + || GL_EXT_texture_sRGB || GL_EXT_texture_compression_s3tc_srgb case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: @@ -2428,6 +2559,7 @@ bool LLImageGL::isCompressed() case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: is_compressed = true; break; +#endif default: break; } @@ -2444,7 +2576,10 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) if (mFormatType != GL_UNSIGNED_BYTE || ((mFormatPrimary != GL_RGBA) - && (mFormatPrimary != GL_SRGB_ALPHA))) +#if GL_VERSION_2_1 + && (mFormatPrimary != GL_SRGB_ALPHA) +#endif + )) { //cannot generate a pick mask for this texture freePickMask(); @@ -2569,6 +2704,8 @@ bool LLImageGL::scaleDown(S32 desired_discard) return false; } + //LL_WARNS() << "scaleDown" << LL_ENDL; + S32 mip = desired_discard - mCurrentDiscardLevel; S32 desired_width = getWidth(desired_discard); @@ -2592,6 +2729,7 @@ bool LLImageGL::scaleDown(S32 desired_discard) free_tex_image(mTexName); glTexImage2D(mTarget, 0, mFormatInternal, desired_width, desired_height, 0, mFormatPrimary, mFormatType, nullptr); glCopyTexSubImage2D(mTarget, 0, 0, 0, 0, 0, desired_width, desired_height); + LOG_GLERROR("LLImageGL::scaleDown() - glCopyTexSubImage2D"); alloc_tex_image(desired_width, desired_height, mFormatInternal, 1); mTexOptionsDirty = true; @@ -2601,6 +2739,7 @@ bool LLImageGL::scaleDown(S32 desired_discard) LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glGenerateMipmap"); gGL.getTexUnit(0)->bind(this); glGenerateMipmap(mTarget); + LOG_GLERROR("LLImageGL::scaleDown() - glGenerateMipmap"); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } } @@ -2630,7 +2769,9 @@ bool LLImageGL::scaleDown(S32 desired_discard) sScratchPBOSize = (U32)size; } +#if GL_VERSION_1_3 glGetTexImage(mTarget, mip, mFormatPrimary, mFormatType, nullptr); +#endif free_tex_image(mTexName); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 6a39a34c4e..c90169eddf 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -80,10 +80,16 @@ bool LLRender::sClassicMode = false; static const GLenum sGLTextureType[] = { GL_TEXTURE_2D, +#if GL_VERSION_3_1 GL_TEXTURE_RECTANGLE, +#endif GL_TEXTURE_CUBE_MAP, +#if GL_VERSION_4_0 GL_TEXTURE_CUBE_MAP_ARRAY, +#endif +#if GL_VERSION_3_2 GL_TEXTURE_2D_MULTISAMPLE, +#endif GL_TEXTURE_3D }; @@ -204,12 +210,14 @@ void LLTexUnit::bindFast(LLTexture* texture) } glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture); mHasMipMaps = gl_tex->mHasMipMaps; +/* if (gl_tex->mTexOptionsDirty) { gl_tex->mTexOptionsDirty = false; setTextureAddressModeFast(gl_tex->mAddressMode, gl_tex->getTarget()); setTextureFilteringOptionFast(gl_tex->mFilterOption, gl_tex->getTarget()); } +*/ } bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind) @@ -464,6 +472,7 @@ void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode) activate(); +/* setTextureAddressModeFast(mode, mCurrTexType); } @@ -475,52 +484,93 @@ void LLTexUnit::setTextureAddressModeFast(eTextureAddressMode mode, eTextureType { glTexParameteri(sGLTextureType[tex_type], GL_TEXTURE_WRAP_R, sGLAddressMode[mode]); } +*/ + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]); + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_T, sGLAddressMode[mode]); + if (mCurrTexType == TT_CUBE_MAP) + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_R, sGLAddressMode[mode]); + } } void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option) { if (mIndex < 0 || mCurrTexture == 0 || mCurrTexType == LLTexUnit::TT_MULTISAMPLE_TEXTURE) return; + GLenum target = sGLTextureType[mCurrTexType]; + + if (mCurrTexType == LLTexUnit::TT_NONE) + { + LL_WARNS() << "setTextureFilteringOption() Error: mCurrTexType==TT_NONE texture: " << mCurrTexture << LL_ENDL; + gGL.debugTexUnits(); + } + gGL.flush(); +/* setTextureFilteringOptionFast(option, mCurrTexType); } void LLTexUnit::setTextureFilteringOptionFast(LLTexUnit::eTextureFilterOptions option, eTextureType tex_type) { +*/ if (option == TFO_POINT) { +/* glTexParameteri(sGLTextureType[tex_type], GL_TEXTURE_MAG_FILTER, GL_NEAREST); } else { glTexParameteri(sGLTextureType[tex_type], GL_TEXTURE_MAG_FILTER, GL_LINEAR); +*/ + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + else + { + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } if (option >= TFO_TRILINEAR && mHasMipMaps) { +/* glTexParameteri(sGLTextureType[tex_type], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); +*/ + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } else if (option >= TFO_BILINEAR) { if (mHasMipMaps) { +/* glTexParameteri(sGLTextureType[tex_type], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); } else { glTexParameteri(sGLTextureType[tex_type], GL_TEXTURE_MIN_FILTER, GL_LINEAR); +*/ + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + } + else + { + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } } else { if (mHasMipMaps) { +/* glTexParameteri(sGLTextureType[tex_type], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); } else { glTexParameteri(sGLTextureType[tex_type], GL_TEXTURE_MIN_FILTER, GL_NEAREST); +*/ + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + } + else + { + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } } @@ -528,6 +578,7 @@ void LLTexUnit::setTextureFilteringOptionFast(LLTexUnit::eTextureFilterOptions o { if (option == TFO_ANISOTROPIC && LLRender::sAnisotropicFilteringLevel > 1.f) { +/* F32 aniso_level = llclamp(LLRender::sAnisotropicFilteringLevel, 1.f, gGLManager.mMaxAnisotropy); glTexParameterf(sGLTextureType[tex_type], GL_TEXTURE_MAX_ANISOTROPY, aniso_level); @@ -535,6 +586,14 @@ void LLTexUnit::setTextureFilteringOptionFast(LLTexUnit::eTextureFilterOptions o else { glTexParameterf(sGLTextureType[tex_type], GL_TEXTURE_MAX_ANISOTROPY, 1.f); +*/ + //glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, gGLManager.mMaxAnisotropy); + //We plan to add a setting. For now we stick to a low value. + glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 4.0); + } + else + { + glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); } } } @@ -786,7 +845,9 @@ bool LLRender::init(bool needs_vertex_buffer) glCullFace(GL_BACK); // necessary for reflection maps +#if GL_VERSION_3_2 glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); +#endif #if LL_WINDOWS if (glGenVertexArrays == nullptr) @@ -811,13 +872,12 @@ bool LLRender::init(bool needs_vertex_buffer) void LLRender::initVertexBuffer() { llassert_always(mBuffer.isNull()); - stop_glerror(); mBuffer = new LLVertexBuffer(immediate_mask); - mBuffer->allocateBuffer(4096, 0); + mBuffer->allocateBuffer(16384, 0); mBuffer->getVertexStrider(mVerticesp); mBuffer->getTexCoord0Strider(mTexcoordsp); mBuffer->getColorStrider(mColorsp); - stop_glerror(); + LOG_GLERROR("LLRender::initVertexBuffer()"); } void LLRender::resetVertexBuffer() @@ -905,7 +965,6 @@ void LLRender::syncLightState() void LLRender::syncMatrices() { - STOP_GLERROR; LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; static const U32 name[] = @@ -1050,7 +1109,7 @@ void LLRender::syncMatrices() syncLightState(); } } - STOP_GLERROR; + LOG_GLERROR("LLRender::syncMatrices()"); } void LLRender::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z) @@ -1461,7 +1520,7 @@ void LLRender::begin(const GLuint& mode) mMode == LLRender::TRIANGLES || mMode == LLRender::POINTS) { - flush(); + flush("LLRender::begin"); } else if (mCount != 0) { @@ -1472,7 +1531,7 @@ void LLRender::begin(const GLuint& mode) } } -void LLRender::end() +void LLRender::end(std::string comment_) { if (mCount == 0) { @@ -1485,13 +1544,12 @@ void LLRender::end() mMode != LLRender::POINTS) || mCount > 2048) { - flush(); + flush("from end " + comment_); } } -void LLRender::flush() +void LLRender::flush(std::string comment_) { - STOP_GLERROR; if (mCount > 0) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; @@ -1560,9 +1618,16 @@ void LLRender::flush() } resetStriders(count); + + LOG_GLERROR("LLRender::flush() end " + comment_); } } +void LLRender::flush() +{ + flush(""); +} + LLVertexBuffer* LLRender::bufferfromCache(U32 attribute_mask, U32 count) { LLVertexBuffer *vb = nullptr; @@ -1666,12 +1731,14 @@ LLVertexBuffer* LLRender::genBuffer(U32 attribute_mask, S32 count) vb->setColorData(mColorsp.get()); } -#if LL_DARWIN + if(gGLManager.mIsApple) + { // unmapBuffer creates the GL buffer, uploads, and leaves it bound, // drawBuffer's later setBuffer() then runs setupVertexBuffer against // a valid VBO. vb->unmapBuffer(); -#endif + } + vb->unbind(); return vb; @@ -1957,7 +2024,8 @@ void LLRender::debugTexUnits(void) std::string active_enabled = "false"; for (U32 i = 0; i < mTexUnits.size(); i++) { - if (getTexUnit(i)->mCurrTexType != LLTexUnit::TT_NONE) + //if (getTexUnit(i)->mCurrTexType != LLTexUnit::TT_NONE) + if(1) { if (i == mCurrTextureUnitIndex) active_enabled = "true"; LL_INFOS("TextureUnit") << "TexUnit: " << i << " Enabled" << LL_ENDL; @@ -1967,14 +2035,27 @@ void LLRender::debugTexUnits(void) case LLTexUnit::TT_TEXTURE: LL_CONT << "Texture 2D"; break; +#if GL_VERSION_3_1 case LLTexUnit::TT_RECT_TEXTURE: LL_CONT << "Texture Rectangle"; break; +#endif case LLTexUnit::TT_CUBE_MAP: LL_CONT << "Cube Map"; break; + case LLTexUnit::TT_CUBE_MAP_ARRAY: + LL_CONT << "Cube Map Array"; + break; + + case LLTexUnit::TT_MULTISAMPLE_TEXTURE: + LL_CONT << "Multisample Texture"; + break; + + case LLTexUnit::TT_TEXTURE_3D: + LL_CONT << "Texture 3D"; + break; default: - LL_CONT << "ARGH!!! NONE!"; + LL_CONT << "ARGH!!! NONE! -> type = " << getTexUnit(i)->mCurrTexType; break; } LL_CONT << ", Texture Bound: " << getTexUnit(i)->mCurrTexture << LL_ENDL; diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 9c17cf3470..13dfe43356 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -34,6 +34,7 @@ //#include "linden_common.h" +#include <array> #include "v2math.h" #include "v3math.h" #include "v4coloru.h" @@ -70,10 +71,16 @@ public: typedef enum { TT_TEXTURE = 0, // Standard 2D Texture +#if GL_VERSION_3_1 TT_RECT_TEXTURE, // Non power of 2 texture +#endif TT_CUBE_MAP, // 6-sided cube map texture +#if GL_VERSION_4_0 TT_CUBE_MAP_ARRAY, // Array of cube maps +#endif +#if GL_VERSION_3_2 TT_MULTISAMPLE_TEXTURE, // see GL_ARB_texture_multisample +#endif TT_TEXTURE_3D, // standard 3D Texture TT_NONE, // No texture type is currently enabled } eTextureType; @@ -209,15 +216,19 @@ public: // Warning: this stays set for the bound texture forever, // make sure you want to permanently change the address mode for the bound texture. void setTextureAddressMode(eTextureAddressMode mode); +/* // MUST already be active and bound void setTextureAddressModeFast(eTextureAddressMode mode, eTextureType tex_type); +*/ // Sets the filtering options used to sample the texture // Warning: this stays set for the bound texture forever, // make sure you want to permanently change the filtering for the bound texture. void setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option); +/* // MUST already be active and bound void setTextureFilteringOptionFast(LLTexUnit::eTextureFilterOptions option, eTextureType tex_type); +*/ static U32 getInternalType(eTextureType type); @@ -414,6 +425,7 @@ public: LLVector3 getUITranslation(); LLVector3 getUIScale(); + void flush(std::string comment_); void flush(); // if list is set, will store buffers in list for later use, if list isn't set, will use cache @@ -421,7 +433,7 @@ public: void endList(); void begin(const GLuint& mode); - void end(); + void end(std::string comment_ = ""); U8 getMode() const { return mMode; } diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index e9d2212a67..821cb7461c 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -833,7 +833,7 @@ void gl_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& c { gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], color.mV[VALPHA]); - gGL.setLineWidth(2.5f); + LLRender2D::setLineWidth(2.5f); gGL.begin(LLRender::LINES); { diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 0b0d69812f..dcee340a71 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -95,7 +95,15 @@ void LLRenderTarget::resize(U32 resx, U32 resy) { gGL.getTexUnit(0)->bindManual(mUsage, mDepth); U32 internal_type = LLTexUnit::getInternalType(mUsage); - LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); + // Apple's GL rejects sized GL_DEPTH_COMPONENT24 with GL_UNSIGNED_INT. +#if LL_DARWIN + const U32 depth_internal = GL_DEPTH_COMPONENT; +#else + const U32 depth_internal = GL_DEPTH_COMPONENT24; +#endif + glGetError(); + LLImageGL::setManualImage(internal_type, 0, depth_internal, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); + glGetError(); sBytesAllocated += pix_diff*4; } @@ -158,6 +166,8 @@ void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name) llassert(mTex.empty()); // mTex must be empty with this mode (binding target should be done via LLImageGL) llassert(!isBoundInStack()); + U32 target = getTarget(); + if (mFBO == 0) { glGenFramebuffers(1, (GLuint*)&mFBO); @@ -174,14 +184,14 @@ void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name) mTex.push_back(use_name); - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + glBindFramebuffer(target, mFBO); + glFramebufferTexture2D(target, GL_COLOR_ATTACHMENT0, LLTexUnit::getInternalType(mUsage), use_name, 0); stop_glerror(); check_framebuffer_status(); - glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); + glBindFramebuffer(target, sCurFBO); } void LLRenderTarget::releaseColorAttachment() @@ -194,6 +204,7 @@ void LLRenderTarget::releaseColorAttachment() glBindFramebuffer(GL_FRAMEBUFFER, mFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, LLTexUnit::getInternalType(mUsage), 0, 0); glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); + LOG_GLERROR(mName + " releaseColorAttachment()"); mTex.clear(); } @@ -208,6 +219,8 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) return true; } + U32 target = getTarget(); + U32 offset = static_cast<U32>(mTex.size()); if( offset >= 4 ) @@ -226,12 +239,76 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) LLImageGL::generateTextures(1, &tex); gGL.getTexUnit(0)->bindManual(mUsage, tex); - stop_glerror(); - + U32 miplevel = mMipLevels; + U32 intformat = color_fmt; + U32 pixformat = GL_RGBA; + U32 pixtype = GL_UNSIGNED_BYTE; { - clear_glerror(); - LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false); + //clear_glerror(); + + if(color_fmt == GL_RGB10_A2) + { + pixformat = GL_RGBA; + pixtype = GL_UNSIGNED_BYTE; + } + else if(color_fmt == GL_R11F_G11F_B10F) + { + pixformat = GL_RGB; + pixtype = GL_HALF_FLOAT; + } + else if(color_fmt == GL_R8) + { + pixformat = GL_RED; + pixtype = GL_UNSIGNED_BYTE; + } + else if(color_fmt == GL_R16F) + { + pixformat = GL_RED; + pixtype = GL_HALF_FLOAT; + } + else if(color_fmt == GL_RG16F) + { + pixformat = GL_RG; + pixtype = GL_HALF_FLOAT; + } + else if(color_fmt == GL_RGBA16F) + { + pixformat = GL_RGBA; + pixtype = GL_HALF_FLOAT; + } + else if(color_fmt == GL_RGB16F) + { + pixformat = GL_RGB; + pixtype = GL_HALF_FLOAT; + } + else if(color_fmt == GL_RGB8) + { + pixformat = GL_RGB; + pixtype = GL_UNSIGNED_BYTE; + } + else if(color_fmt == GL_RGB) + { + pixformat = GL_RGB; + pixtype = GL_UNSIGNED_BYTE; + } + else if(color_fmt == GL_RGBA) + { + pixformat = GL_RGBA; + pixtype = GL_UNSIGNED_BYTE; + } + else if(color_fmt == GL_RGBA8) + { + pixformat = GL_RGBA; + pixtype = GL_UNSIGNED_BYTE; + } + else + { + pixformat = GL_RGBA; + pixtype = GL_UNSIGNED_BYTE; + } + + LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, pixformat, pixtype, NULL, false); if (glGetError() != GL_NO_ERROR) { LL_WARNS() << "Could not allocate color buffer for render target." << LL_ENDL; @@ -241,30 +318,29 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) sBytesAllocated += mResX*mResY*4; - stop_glerror(); - - if (offset == 0) { //use bilinear filtering on single texture render targets that aren't multisampled gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - stop_glerror(); + LOG_GLERROR(mName + " setting filtering to TFO_BILINEAR"); } else { //don't filter data attachments gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - stop_glerror(); + LOG_GLERROR(mName + " setting filtering to TFO_POINT"); } +#if GL_VERSION_3_1 if (mUsage != LLTexUnit::TT_RECT_TEXTURE) { gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); - stop_glerror(); + LOG_GLERROR(mName + " setting address mode to TAM_MIRROR"); } else +#endif { // ATI doesn't support mirrored repeat for rectangular textures. gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - stop_glerror(); + LOG_GLERROR(mName + " setting address mode to TAM_CLAMP"); } if (mFBO) @@ -283,7 +359,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) if (gDebugGL) { //bind and unbind to validate target - bindTarget(); + bindTarget(mName, mMode); flush(); } @@ -298,8 +374,6 @@ bool LLRenderTarget::allocateDepth() gGL.getTexUnit(0)->bindManual(mUsage, mDepth); U32 internal_type = LLTexUnit::getInternalType(mUsage); - stop_glerror(); - clear_glerror(); LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); @@ -307,7 +381,7 @@ bool LLRenderTarget::allocateDepth() if (glGetError() != GL_NO_ERROR) { - LL_WARNS() << "Unable to allocate depth buffer for render target." << LL_ENDL; + LL_WARNS() << "Unable to allocate depth buffer for render target " << mName << LL_ENDL; return false; } @@ -343,6 +417,8 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); + LOG_GLERROR(mName + " shareDepthBuffer()"); + target.mUseDepth = true; } } @@ -406,19 +482,32 @@ void LLRenderTarget::release() LLImageGL::deleteTextures(1, &mTex[0]); } + LOG_GLERROR(mName + " release()"); + mTex.clear(); mInternalFormat.clear(); mResX = mResY = 0; } -void LLRenderTarget::bindTarget() +void LLRenderTarget::bindTarget(std::string name_, U32 mode_) { LL_PROFILE_GPU_ZONE("bindTarget"); llassert(mFBO); llassert(!isBoundInStack()); - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + //mode_ = 0; + + mMode = mode_; + mName = name_; + + U32 target = getTarget(); + + glBindFramebuffer(target, mFBO); + LOG_GLERROR(mName+" bindTarget()"); + + //attach(); + sCurFBO = mFBO; //setup multiple render targets @@ -429,15 +518,32 @@ void LLRenderTarget::bindTarget() if (mTex.empty()) { //no color buffer to draw to - glDrawBuffer(GL_NONE); + if(!mUseDepth) LL_WARNS() << mName << " HAS NO COLOR BUFFER AND NO DEPTH!!" << LL_ENDL; + GLenum buffers[] = {GL_NONE}; + glDrawBuffers(0, buffers); glReadBuffer(GL_NONE); } - else + else if(mMode == 0) { glDrawBuffers(static_cast<GLsizei>(mTex.size()), drawbuffers); glReadBuffer(GL_COLOR_ATTACHMENT0); + LOG_GLERROR(mName+" read and write buffers"); + } + else if(mMode == 1) + { + glDrawBuffers(static_cast<GLsizei>(mTex.size()), drawbuffers); + //glReadBuffer(GL_NONE); + LOG_GLERROR(mName+" draw buffer"); } + else if(mMode == 2) + { + //glDrawBuffer(GL_NONE); + glReadBuffer(GL_COLOR_ATTACHMENT0); + LOG_GLERROR(mName+" read buffer"); + } + check_framebuffer_status(); + LOG_GLERROR(mName+" checked status"); glViewport(0, 0, mResX, mResY); sCurResX = mResX; @@ -451,7 +557,9 @@ void LLRenderTarget::clear(U32 mask_in) { LL_PROFILE_GPU_ZONE("clear"); llassert(mFBO); - U32 mask = GL_COLOR_BUFFER_BIT; + U32 mask = 0; + + if(!mTex.empty()) mask |= GL_COLOR_BUFFER_BIT; if (mUseDepth) { mask |= GL_DEPTH_BUFFER_BIT; @@ -460,15 +568,14 @@ void LLRenderTarget::clear(U32 mask_in) if (mFBO) { check_framebuffer_status(); - stop_glerror(); glClear(mask & mask_in); - stop_glerror(); + LOG_GLERROR(mName + "clear()"); } else { LLGLEnable scissor(GL_SCISSOR_TEST); glScissor(0, 0, mResX, mResY); - stop_glerror(); + LOG_GLERROR(""); glClear(mask & mask_in); } } @@ -493,29 +600,43 @@ void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilt { gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index), filter_options == LLTexUnit::TFO_TRILINEAR || filter_options == LLTexUnit::TFO_ANISOTROPIC); gGL.getTexUnit(channel)->setTextureFilteringOption(filter_options); + + LOG_GLERROR(mName + " bindTexture()"); } void LLRenderTarget::flush() { LL_PROFILE_GPU_ZONE("rt flush"); + + LOG_GLERROR(mName+" rt flush() A"); + gGL.flush(); llassert(mFBO); llassert(sCurFBO == mFBO); llassert(sBoundTarget == this); - if (mGenerateMipMaps == LLTexUnit::TMG_AUTO) + if (mGenerateMipMaps == LLTexUnit::TMG_AUTO && mMode != 2) { LL_PROFILE_GPU_ZONE("rt generate mipmaps"); - bindTexture(0, 0, LLTexUnit::TFO_TRILINEAR); + //bindTexture(0, 0, LLTexUnit::TFO_TRILINEAR); + bindTexture(0, 0, LLTexUnit::TFO_ANISOTROPIC); glGenerateMipmap(GL_TEXTURE_2D); + LOG_GLERROR(mName + " glGenerateMipmap()"); } + LOG_GLERROR(mName + " rt flush() B"); + + unbind(); +} + +void LLRenderTarget::unbind() +{ if (mPreviousRT) { // a bit hacky -- pop the RT stack back two frames and push // the previous frame back on to play nice with the GL state machine sBoundTarget = mPreviousRT->mPreviousRT; - mPreviousRT->bindTarget(); + mPreviousRT->bindTarget(mPreviousRT->mName, mPreviousRT->mMode); } else { @@ -528,6 +649,8 @@ void LLRenderTarget::flush() glReadBuffer(GL_BACK); glDrawBuffer(GL_BACK); } + + LOG_GLERROR(mName + " rt unbind()"); } bool LLRenderTarget::isComplete() const @@ -582,3 +705,13 @@ void LLRenderTarget::swapFBORefs(LLRenderTarget& other) std::swap(mFBO, other.mFBO); std::swap(mTex, other.mTex); } + +U32 LLRenderTarget::getTarget() +{ + U32 target = GL_FRAMEBUFFER; + + if(mMode == 1) target = GL_DRAW_FRAMEBUFFER; + else if(mMode == 2) target = GL_READ_FRAMEBUFFER; + + return target; +} diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index ea4c38d483..95e2ef1d2c 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -126,7 +126,7 @@ public: // If an LLRenderTarget is currently bound, stores a reference to that LLRenderTarget // and restores previous binding on flush() (maintains a stack of Render Targets) // Asserts that this target is not currently bound in the stack - void bindTarget(); + void bindTarget(std::string name_ = "nd", U32 mode_ = 0); //clear render targer, clears depth buffer if present, //uses scissor rect if in copy-to-texture mode @@ -158,6 +158,7 @@ public: // If an LLRenderTarget was bound when bindTarget was called, binds that RenderTarget for rendering (maintains RT stack) // asserts that this target is currently bound void flush(); + void unbind(); //Returns TRUE if target is ready to be rendered into. //That is, if the target has been allocated with at least @@ -174,11 +175,15 @@ public: static LLRenderTarget* sBoundTarget; + U32 mMode; + std::string mName; + protected: U32 mResX; U32 mResY; std::vector<U32> mTex; std::vector<U32> mInternalFormat; + std::vector<U32> mPixFormat; U32 mFBO; LLRenderTarget* mPreviousRT = nullptr; @@ -188,6 +193,10 @@ protected: U32 mMipLevels; LLTexUnit::eTextureType mUsage; + +private: + U32 getTarget(); + }; #endif diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 9f7c244fe9..5030e004f6 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -263,6 +263,7 @@ bool LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) } } + /* if (features->hasGamma || features->isDeferred) { if (!shader->attachFragmentObject("windlight/gammaF.glsl")) @@ -270,6 +271,7 @@ bool LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) return false; } } + */ if (features->hasAtmospherics || features->isDeferred) { @@ -578,7 +580,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev } else { - shader_code_text[shader_code_count++] = strdup("#version 400\n"); + shader_code_text[shader_code_count++] = strdup("#version 410\n"); } } else if (major_version == 3) @@ -1602,6 +1604,20 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("searchTex"); mReservedUniforms.push_back("blendTex"); + mReservedUniforms.push_back("bloomEMap"); + mReservedUniforms.push_back("bloomBlurredMap"); + mReservedUniforms.push_back("bloomHorizontal"); + mReservedUniforms.push_back("bloomBlurRadius"); + mReservedUniforms.push_back("bloomExtractBrightness"); + mReservedUniforms.push_back("bloomStrength"); + mReservedUniforms.push_back("bloomExtractEmissive"); + mReservedUniforms.push_back("bloomExtractEmissive2"); + mReservedUniforms.push_back("bloomExtractORM"); + mReservedUniforms.push_back("bloomExtractMetal"); + mReservedUniforms.push_back("bloomExtractNonMetal"); + mReservedUniforms.push_back("bloomClampValue"); + mReservedUniforms.push_back("mpHDRBoost"); + llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS); std::set<std::string> dupe_check; diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 1b638e6e06..4cfa78632b 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -341,6 +341,20 @@ public: SMAA_SEARCH_TEX, // "searchTex" SMAA_BLEND_TEX, // "blendTex" + BLOOM_EMAP, // "bloomEMap" + BLOOM_BMAP, // "bloomBlurredMap" + BLOOM_BLURH, // "bloomHorizontal" + BLOOM_BLUR_RADIUS, // "bloomRadius" + BLOOM_EXTRACT_BRIGHTNESS, // "bloomExtractBrightness" + BLOOM_STRENGTH, // "bloomStrength" + BLOOM_EXTRACT_EMISSIVE, // "bloomExtractEmissive" + BLOOM_EXTRACT_EMISSIVE2, // "bloomExtractEmissive2" + BLOOM_EXTRACT_ORM, // "bloomExtractORM" + BLOOM_EXTRACT_METAL, // "bloomExtractMetal" + BLOOM_EXTRACT_NONMETAL, // "bloomExtractNonMetal" + BLOOM_CLAMP, // "bloomClampValue" + MP_HDR_BOOST, // "mpHDRBoost" + END_RESERVED_UNIFORMS } eGLSLReservedUniforms; // clang-format on diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 2d64292fe7..6a885d2a09 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -29,7 +29,6 @@ #include "llfasttimer.h" #include "llsys.h" #include "llvertexbuffer.h" -// #include "llrender.h" #include "llglheaders.h" #include "llrender.h" #include "llvector4a.h" @@ -263,7 +262,7 @@ static GLuint gen_buffer() LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; GLuint ret = 0; - constexpr U32 pool_size = 4096; + constexpr U32 pool_size = 32768; thread_local static GLuint sNamePool[pool_size]; thread_local static U32 sIndex = 0; @@ -278,13 +277,15 @@ static GLuint gen_buffer() glGenBuffers(pool_size, sNamePool); } else -#endif { // work around for AMD driver bug for (U32 i = 0; i < pool_size; ++i) { glGenBuffers(1, sNamePool + i); } } +#else + glGenBuffers(pool_size, sNamePool); +#endif } ret = sNamePool[--sIndex]; @@ -314,7 +315,27 @@ static void delete_buffers(S32 count, GLuint* buffers) if (!sFreeList[idx].empty()) { - glDeleteBuffers((GLsizei)sFreeList[idx].size(), sFreeList[idx].data()); + if (gGLManager.mIsApple) + { + // Unbind, then delete one name at a time. Do not glFinish(): + // that drains a queued glWaitSync and faults in + // GLDFenceRec::getStatus when Apple's fence record is null. + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + LLVertexBuffer::sGLRenderBuffer = 0; + LLVertexBuffer::sGLRenderIndices = 0; + for (GLuint name : sFreeList[idx]) + { + if (name) + { + glDeleteBuffers(1, &name); + } + } + } + else + { + glDeleteBuffers((GLsizei)sFreeList[idx].size(), sFreeList[idx].data()); + } sFreeList[idx].resize(0); } } @@ -358,10 +379,16 @@ public: { //allocate a new buffer LL_PROFILE_GPU_ZONE("vbo alloc"); - // ON OS X, we don't allocate a VBO until the last possible moment - // in unmapBuffer data = (U8*) ll_aligned_malloc_16(size); - STOP_GLERROR; + + if (type == GL_ARRAY_BUFFER) + { + LLVertexBuffer::sGLRenderBuffer = name; + } + else + { + LLVertexBuffer::sGLRenderIndices = name; + } } } @@ -377,12 +404,10 @@ public: } mAllocated -= size; - STOP_GLERROR; if (name) { delete_buffers(1, &name); } - STOP_GLERROR; } }; @@ -455,7 +480,7 @@ public: mMisses++; name = gen_buffer(); glBindBuffer(type, name); - glBufferData(type, size, nullptr, GL_DYNAMIC_DRAW); + glBufferData(type, size, nullptr, GL_STREAM_DRAW); if (type == GL_ELEMENT_ARRAY_BUFFER) { LLVertexBuffer::sGLRenderIndices = name; @@ -685,6 +710,15 @@ U32 LLVertexBuffer::sGLRenderIndices = 0; U32 LLVertexBuffer::sLastMask = 0; U32 LLVertexBuffer::sVertexCount = 0; +// The viewer keeps a single VAO bound. Attribute pointer calls store state in +// that VAO and capture the current array buffer. Track the formats configured +// for sGLRenderBuffer to avoid resubmitting identical state to OpenGL-on-Metal. +// If VAO switching is introduced, invalidate this cache when the VAO changes. +static U32 sVertexAttribsConfigured = 0; +static U32 sColorPointerSource = 0; +static constexpr U32 COLOR_POINTER_COLOR = 1; +static constexpr U32 COLOR_POINTER_EMISSIVE = 2; + //NOTE: each component must be AT LEAST 4 bytes in size to avoid a performance penalty on AMD hardware const U32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] = @@ -786,7 +820,6 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; llassert(LLGLSLShader::sCurBoundShaderPtr != NULL); - STOP_GLERROR; gGL.syncMatrices(); @@ -906,10 +939,8 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi llassert(mGLBuffer == sGLRenderBuffer); llassert(mGLIndices == sGLRenderIndices); gGL.syncMatrices(); - STOP_GLERROR; glDrawRangeElements(sGLMode[mode], start, end, count, mIndicesType, (GLvoid*) (indices_offset * (size_t) mIndicesStride)); - STOP_GLERROR; } void LLVertexBuffer::drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const @@ -932,9 +963,7 @@ 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 @@ -942,14 +971,14 @@ void LLVertexBuffer::initClass(LLWindow* window) { llassert(sVBOPool == nullptr); -#if LL_DARWIN || LL_ARM64 +//#if LL_DARWIN || LL_ARM64 if (gGLManager.mIsApple) { LL_INFOS() << "VBO Pooling Disabled" << LL_ENDL; sVBOPool = new LLAppleVBOPool(); } else -#endif +//#endif { LL_INFOS() << "VBO Pooling Enabled" << LL_ENDL; sVBOPool = new LLDefaultVBOPool(); @@ -969,12 +998,12 @@ 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; + sVertexAttribsConfigured = 0; + sColorPointerSource = 0; } //static @@ -1287,12 +1316,12 @@ U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 inde count = mNumVerts - index; } -#if LL_DARWIN || LL_ARM64 +//#if LL_DARWIN || LL_ARM64 // Region tracking not needed on apple silicon - it recreates entire buffer // While mIsApple can be encountered under windows, this is a // macOS OpenGL behavior workaround. LL_ARM64 check might be not needed if (!gGLManager.mIsApple) -#endif +//#endif { U32 start = mOffsets[type] + sTypeSize[type] * index; U32 end = start + sTypeSize[type] * count-1; @@ -1329,9 +1358,9 @@ U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count) count = mNumIndices-index; } -#if LL_DARWIN || LL_ARM64 +//#if LL_DARWIN || LL_ARM64 if (!gGLManager.mIsApple) -#endif +//#endif { U32 start = sizeof(U16) * index; U32 end = start + sizeof(U16) * count-1; @@ -1366,7 +1395,7 @@ U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count) // dst -- mMappedData or mMappedIndexData void LLVertexBuffer::flush_vbo(GLenum target, U32 start, U32 end, void* data, U8* dst) { -#if LL_DARWIN || LL_ARM64 +//#if LL_DARWIN || LL_ARM64 if (gGLManager.mIsApple) { // on OS X, flush_vbo doesn't actually write to the GL buffer, so be sure to call @@ -1378,7 +1407,7 @@ void LLVertexBuffer::flush_vbo(GLenum target, U32 start, U32 end, void* data, U8 memcpy(dst+start, data, end-start+1); } else -#endif +//#endif { llassert(target == GL_ARRAY_BUFFER ? sGLRenderBuffer == mGLBuffer : sGLRenderIndices == mGLIndices); @@ -1420,7 +1449,6 @@ void LLVertexBuffer::_mapBuffer() void LLVertexBuffer::_unmapBuffer() { - STOP_GLERROR; if (!mMapped) { return; @@ -1434,7 +1462,7 @@ void LLVertexBuffer::_unmapBuffer() } }; -#if LL_DARWIN || LL_ARM64 +//#if LL_DARWIN || LL_ARM64 if (gGLManager.mIsApple) { STOP_GLERROR; @@ -1447,12 +1475,16 @@ void LLVertexBuffer::_unmapBuffer() mGLBuffer = gen_buffer(); glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); sGLRenderBuffer = mGLBuffer; - glBufferData(GL_ARRAY_BUFFER, mSize, mMappedData, GL_STATIC_DRAW); + sVertexAttribsConfigured = 0; + sColorPointerSource = 0; + glBufferData(GL_ARRAY_BUFFER, mSize, mMappedData, GL_STREAM_DRAW ); } else if (mGLBuffer != sGLRenderBuffer) { glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); sGLRenderBuffer = mGLBuffer; + sVertexAttribsConfigured = 0; + sColorPointerSource = 0; } STOP_GLERROR; @@ -1467,7 +1499,7 @@ void LLVertexBuffer::_unmapBuffer() glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); sGLRenderIndices = mGLIndices; - glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndicesSize, mMappedIndexData, GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndicesSize, mMappedIndexData, GL_STREAM_DRAW ); } else if (mGLIndices != sGLRenderIndices) { @@ -1477,7 +1509,7 @@ void LLVertexBuffer::_unmapBuffer() STOP_GLERROR; } else -#endif // LL_DARWIN || LL_ARM64 +//#endif // LL_DARWIN || LL_ARM64 { if (!mMappedVertexRegions.empty()) { @@ -1692,10 +1724,12 @@ void LLVertexBuffer::setBuffer() { glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); sGLRenderBuffer = mGLBuffer; + sVertexAttribsConfigured = 0; + sColorPointerSource = 0; setupVertexBuffer(); } - else if (sLastMask != data_mask) + else if (gGLManager.mIsApple || sLastMask != data_mask) { setupVertexBuffer(); sLastMask = data_mask; @@ -1718,98 +1752,108 @@ void LLVertexBuffer::setupVertexBuffer() U8* base = nullptr; U32 data_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask; + U32 setup_mask = gGLManager.mIsApple ? + data_mask & ~sVertexAttribsConfigured : data_mask; - if (data_mask & MAP_NORMAL) + if (setup_mask & MAP_NORMAL) { AttributeType loc = TYPE_NORMAL; void* ptr = (void*)(base + mOffsets[TYPE_NORMAL]); glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr); } - if (data_mask & MAP_TEXCOORD3) + if (setup_mask & MAP_TEXCOORD3) { AttributeType loc = TYPE_TEXCOORD3; void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]); glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr); } - if (data_mask & MAP_TEXCOORD2) + if (setup_mask & MAP_TEXCOORD2) { AttributeType loc = TYPE_TEXCOORD2; void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]); glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr); } - if (data_mask & MAP_TEXCOORD1) + if (setup_mask & MAP_TEXCOORD1) { AttributeType loc = TYPE_TEXCOORD1; void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD1]); glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr); } - if (data_mask & MAP_TANGENT) + if (setup_mask & MAP_TANGENT) { AttributeType loc = TYPE_TANGENT; void* ptr = (void*)(base + mOffsets[TYPE_TANGENT]); glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr); } - if (data_mask & MAP_TEXCOORD0) + if (setup_mask & MAP_TEXCOORD0) { AttributeType loc = TYPE_TEXCOORD0; void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]); glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr); } - if (data_mask & MAP_COLOR) + const U32 desired_color_source = (data_mask & MAP_EMISSIVE) ? + COLOR_POINTER_EMISSIVE : + ((data_mask & MAP_COLOR) ? COLOR_POINTER_COLOR : 0); + if (desired_color_source && + (!gGLManager.mIsApple || desired_color_source != sColorPointerSource)) { AttributeType loc = TYPE_COLOR; - //bind emissive instead of color pointer if emissive is present - void* ptr = (data_mask & MAP_EMISSIVE) ? (void*)(base + mOffsets[TYPE_EMISSIVE]) : (void*)(base + mOffsets[TYPE_COLOR]); + void* ptr = desired_color_source == COLOR_POINTER_EMISSIVE ? + (void*)(base + mOffsets[TYPE_EMISSIVE]) : + (void*)(base + mOffsets[TYPE_COLOR]); glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr); + sColorPointerSource = desired_color_source; } - if (data_mask & MAP_EMISSIVE) + if (setup_mask & MAP_EMISSIVE) { AttributeType loc = TYPE_EMISSIVE; void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]); glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); - - if (!(data_mask & MAP_COLOR)) - { //map emissive to color channel when color is not also being bound to avoid unnecessary shader swaps - loc = TYPE_COLOR; - glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); - } } - if (data_mask & MAP_WEIGHT) + if (setup_mask & MAP_WEIGHT) { AttributeType loc = TYPE_WEIGHT; void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]); glVertexAttribPointer(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr); } - if (data_mask & MAP_WEIGHT4) + if (setup_mask & MAP_WEIGHT4) { AttributeType loc = TYPE_WEIGHT4; void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT4]); glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr); } - if (data_mask & MAP_JOINT) + if (setup_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) + if (setup_mask & MAP_CLOTHWEIGHT) { AttributeType loc = TYPE_CLOTHWEIGHT; void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]); glVertexAttribPointer(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr); } - if (data_mask & MAP_TEXTURE_INDEX) + if (setup_mask & MAP_TEXTURE_INDEX) { AttributeType loc = TYPE_TEXTURE_INDEX; void* ptr = (void*)(base + mOffsets[TYPE_VERTEX] + 12); glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); } - if (data_mask & MAP_VERTEX) + if (setup_mask & MAP_VERTEX) { AttributeType loc = TYPE_VERTEX; void* ptr = (void*)(base + mOffsets[TYPE_VERTEX]); glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); } + if (gGLManager.mIsApple) + { + sVertexAttribsConfigured |= data_mask; + if (desired_color_source) + { + sVertexAttribsConfigured |= MAP_COLOR; + } + } STOP_GLERROR; } |
