summaryrefslogtreecommitdiff
path: root/indra/llrender
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llrender')
-rw-r--r--indra/llrender/CMakeLists.txt4
-rw-r--r--indra/llrender/llatmosphere.cpp8
-rw-r--r--indra/llrender/llcubemap.cpp275
-rw-r--r--indra/llrender/llcubemap.h24
-rw-r--r--indra/llrender/llcubemaparray.cpp177
-rw-r--r--indra/llrender/llcubemaparray.h68
-rw-r--r--indra/llrender/llgl.cpp2873
-rw-r--r--indra/llrender/llgl.h78
-rw-r--r--indra/llrender/llglcommonfunc.cpp5
-rw-r--r--indra/llrender/llgldbg.cpp223
-rw-r--r--indra/llrender/llgldbg.h34
-rw-r--r--indra/llrender/llglheaders.h1277
-rw-r--r--indra/llrender/llglslshader.cpp1294
-rw-r--r--indra/llrender/llglslshader.h392
-rw-r--r--indra/llrender/llglstates.h100
-rw-r--r--indra/llrender/llgltexture.cpp19
-rw-r--r--indra/llrender/llgltexture.h8
-rw-r--r--indra/llrender/llimagegl.cpp375
-rw-r--r--indra/llrender/llimagegl.h44
-rw-r--r--indra/llrender/llpostprocess.cpp152
-rw-r--r--indra/llrender/llpostprocess.h4
-rw-r--r--indra/llrender/llrender.cpp331
-rw-r--r--indra/llrender/llrender.h90
-rw-r--r--indra/llrender/llrender2dutils.cpp17
-rw-r--r--indra/llrender/llrender2dutils.h2
-rw-r--r--indra/llrender/llrendernavprim.cpp2
-rw-r--r--indra/llrender/llrendertarget.cpp919
-rw-r--r--indra/llrender/llrendertarget.h47
-rw-r--r--indra/llrender/llshadermgr.cpp787
-rw-r--r--indra/llrender/llshadermgr.h70
-rw-r--r--indra/llrender/llvertexbuffer.cpp2688
-rw-r--r--indra/llrender/llvertexbuffer.h303
32 files changed, 6216 insertions, 6474 deletions
diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt
index c5cf1100d5..9454943dc5 100644
--- a/indra/llrender/CMakeLists.txt
+++ b/indra/llrender/CMakeLists.txt
@@ -12,12 +12,12 @@ include(LLWindow)
set(llrender_SOURCE_FILES
llatmosphere.cpp
llcubemap.cpp
+ llcubemaparray.cpp
llfontbitmapcache.cpp
llfontfreetype.cpp
llfontgl.cpp
llfontregistry.cpp
llgl.cpp
- llgldbg.cpp
llglslshader.cpp
llgltexture.cpp
llimagegl.cpp
@@ -39,12 +39,12 @@ set(llrender_HEADER_FILES
llatmosphere.h
llcubemap.h
+ llcubemaparray.h
llfontgl.h
llfontfreetype.h
llfontbitmapcache.h
llfontregistry.h
llgl.h
- llgldbg.h
llglheaders.h
llglslshader.h
llglstates.h
diff --git a/indra/llrender/llatmosphere.cpp b/indra/llrender/llatmosphere.cpp
index ffc17c89f8..8e37ca9b90 100644
--- a/indra/llrender/llatmosphere.cpp
+++ b/indra/llrender/llatmosphere.cpp
@@ -241,7 +241,7 @@ LLGLTexture* LLAtmosphere::getTransmittance()
m_transmittance->generateGLTexture();
m_transmittance->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
m_transmittance->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
- m_transmittance->setExplicitFormat(GL_RGB32F_ARB, GL_RGB, GL_FLOAT);
+ m_transmittance->setExplicitFormat(GL_RGB32F, GL_RGB, GL_FLOAT);
m_transmittance->setTarget(GL_TEXTURE_2D, LLTexUnit::TT_TEXTURE);
}
return m_transmittance;
@@ -255,7 +255,7 @@ LLGLTexture* LLAtmosphere::getScattering()
m_scattering->generateGLTexture();
m_scattering->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
m_scattering->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
- m_scattering->setExplicitFormat(GL_RGB16F_ARB, GL_RGB, GL_FLOAT);
+ m_scattering->setExplicitFormat(GL_RGB16F, GL_RGB, GL_FLOAT);
m_scattering->setTarget(GL_TEXTURE_3D, LLTexUnit::TT_TEXTURE_3D);
}
return m_scattering;
@@ -269,7 +269,7 @@ LLGLTexture* LLAtmosphere::getMieScattering()
m_mie_scatter_texture->generateGLTexture();
m_mie_scatter_texture->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
m_mie_scatter_texture->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
- m_mie_scatter_texture->setExplicitFormat(GL_RGB16F_ARB, GL_RGB, GL_FLOAT);
+ m_mie_scatter_texture->setExplicitFormat(GL_RGB16F, GL_RGB, GL_FLOAT);
m_mie_scatter_texture->setTarget(GL_TEXTURE_3D, LLTexUnit::TT_TEXTURE_3D);
}
return m_mie_scatter_texture;
@@ -283,7 +283,7 @@ LLGLTexture* LLAtmosphere::getIlluminance()
m_illuminance->generateGLTexture();
m_illuminance->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
m_illuminance->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
- m_illuminance->setExplicitFormat(GL_RGB32F_ARB, GL_RGB, GL_FLOAT);
+ m_illuminance->setExplicitFormat(GL_RGB32F, GL_RGB, GL_FLOAT);
m_illuminance->setTarget(GL_TEXTURE_2D, LLTexUnit::TT_TEXTURE);
}
return m_illuminance;
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp
index 834084674e..254288a86e 100644
--- a/indra/llrender/llcubemap.cpp
+++ b/indra/llrender/llcubemap.cpp
@@ -40,8 +40,9 @@
#include "llglheaders.h"
-const F32 epsilon = 1e-7f;
-const U16 RESOLUTION = 64;
+namespace {
+ const U16 RESOLUTION = 64;
+}
bool LLCubeMap::sUseCubeMaps = true;
@@ -50,12 +51,12 @@ LLCubeMap::LLCubeMap(bool init_as_srgb)
mMatrixStage(0),
mIssRGB(init_as_srgb)
{
- mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
- mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
- mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
- mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
- mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
- mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
+ mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
+ mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
+ mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
+ mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
+ mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
}
LLCubeMap::~LLCubeMap()
@@ -66,7 +67,7 @@ void LLCubeMap::initGL()
{
llassert(gGLManager.mInited);
- if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
+ if (LLCubeMap::sUseCubeMaps)
{
// Not initialized, do stuff.
if (mImages[0].isNull())
@@ -166,6 +167,73 @@ void LLCubeMap::init(const std::vector<LLPointer<LLImageRaw> >& rawimages)
}
}
+void LLCubeMap::initReflectionMap(U32 resolution, U32 components)
+{
+ U32 texname = 0;
+
+ LLImageGL::generateTextures(1, &texname);
+
+ mImages[0] = new LLImageGL(resolution, resolution, components, TRUE);
+ mImages[0]->setTexName(texname);
+ mImages[0]->setTarget(mTargets[0], LLTexUnit::TT_CUBE_MAP);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname);
+ mImages[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
+}
+
+void LLCubeMap::initEnvironmentMap(const std::vector<LLPointer<LLImageRaw> >& rawimages)
+{
+ llassert(rawimages.size() == 6);
+
+ U32 texname = 0;
+
+ LLImageGL::generateTextures(1, &texname);
+
+ U32 resolution = rawimages[0]->getWidth();
+ U32 components = rawimages[0]->getComponents();
+
+ for (int i = 0; i < 6; i++)
+ {
+ llassert(rawimages[i]->getWidth() == resolution);
+ llassert(rawimages[i]->getHeight() == resolution);
+ llassert(rawimages[i]->getComponents() == components);
+
+ mImages[i] = new LLImageGL(resolution, resolution, components, TRUE);
+ mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP);
+ mRawImages[i] = rawimages[i];
+ mImages[i]->createGLTexture(0, mRawImages[i], texname);
+
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname);
+ mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP);
+ stop_glerror();
+
+ mImages[i]->setSubImage(mRawImages[i], 0, 0, resolution, resolution);
+ }
+ enableTexture(0);
+ bind();
+ mImages[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+ glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+ glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
+ gGL.getTexUnit(0)->disable();
+ disable();
+}
+
+void LLCubeMap::generateMipMaps()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+
+ mImages[0]->setUseMipMaps(TRUE);
+ mImages[0]->setHasMipMaps(TRUE);
+ enableTexture(0);
+ bind();
+ mImages[0]->setFilteringOption(LLTexUnit::TFO_BILINEAR);
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("cmgmm - glGenerateMipmap");
+ glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
+ }
+ gGL.getTexUnit(0)->disable();
+ disable();
+}
+
GLuint LLCubeMap::getGLName()
{
return mImages[0]->getTexName();
@@ -184,7 +252,7 @@ void LLCubeMap::enable(S32 stage)
void LLCubeMap::enableTexture(S32 stage)
{
mTextureStage = stage;
- if (gGLManager.mHasCubeMap && stage >= 0 && LLCubeMap::sUseCubeMaps)
+ if (stage >= 0 && LLCubeMap::sUseCubeMaps)
{
gGL.getTexUnit(stage)->enable(LLTexUnit::TT_CUBE_MAP);
}
@@ -197,7 +265,7 @@ void LLCubeMap::disable(void)
void LLCubeMap::disableTexture(void)
{
- if (gGLManager.mHasCubeMap && mTextureStage >= 0 && LLCubeMap::sUseCubeMaps)
+ if (mTextureStage >= 0 && LLCubeMap::sUseCubeMaps)
{
gGL.getTexUnit(mTextureStage)->disable();
if (mTextureStage == 0)
@@ -256,191 +324,6 @@ void LLCubeMap::restoreMatrix()
}*/
}
-void LLCubeMap::setReflection (void)
-{
- gGL.getTexUnit(mTextureStage)->bindManual(LLTexUnit::TT_CUBE_MAP, getGLName());
- mImages[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
- mImages[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
-}
-
-LLVector3 LLCubeMap::map(U8 side, U16 v_val, U16 h_val) const
-{
- LLVector3 dir;
-
- const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z
- const S8 side_dir = (((side & 1) << 1) - 1); // even = -1, odd = 1
- const U8 i_coef = (curr_coef + 1) % 3;
- const U8 j_coef = (i_coef + 1) % 3;
-
- dir.mV[curr_coef] = side_dir;
-
- switch (side)
- {
- case 0: // negative X
- dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
- break;
- case 1: // positive X
- dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
- break;
- case 2: // negative Y
- dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
- break;
- case 3: // positive Y
- dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
- dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
- break;
- case 4: // negative Z
- dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
- break;
- case 5: // positive Z
- dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
- break;
- default:
- dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
- dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
- }
-
- dir.normVec();
- return dir;
-}
-
-
-BOOL LLCubeMap::project(F32& v_val, F32& h_val, BOOL& outside,
- U8 side, const LLVector3& dir) const
-{
- const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z
- const S8 side_dir = (((side & 1) << 1) - 1); // even = -1, odd = 1
- const U8 i_coef = (curr_coef + 1) % 3;
- const U8 j_coef = (i_coef + 1) % 3;
-
- outside = TRUE;
- if (side_dir * dir.mV[curr_coef] < 0)
- return FALSE;
-
- LLVector3 ray;
-
- F32 norm_val = fabs(dir.mV[curr_coef]);
-
- if (norm_val < epsilon)
- norm_val = 1e-5f;
-
- ray.mV[curr_coef] = side_dir;
- ray.mV[i_coef] = dir.mV[i_coef] / norm_val;
- ray.mV[j_coef] = dir.mV[j_coef] / norm_val;
-
-
- const F32 i_val = (ray.mV[i_coef] + 1) * 0.5f * RESOLUTION;
- const F32 j_val = (ray.mV[j_coef] + 1) * 0.5f * RESOLUTION;
-
- switch (side)
- {
- case 0: // negative X
- v_val = RESOLUTION - i_val;
- h_val = j_val;
- break;
- case 1: // positive X
- v_val = RESOLUTION - i_val;
- h_val = RESOLUTION - j_val;
- break;
- case 2: // negative Y
- v_val = RESOLUTION - i_val;
- h_val = j_val;
- break;
- case 3: // positive Y
- v_val = i_val;
- h_val = j_val;
- break;
- case 4: // negative Z
- v_val = RESOLUTION - j_val;
- h_val = RESOLUTION - i_val;
- break;
- case 5: // positive Z
- v_val = RESOLUTION - j_val;
- h_val = i_val;
- break;
- default:
- v_val = i_val;
- h_val = j_val;
- }
-
- outside = ((v_val < 0) || (v_val > RESOLUTION) ||
- (h_val < 0) || (h_val > RESOLUTION));
-
- return TRUE;
-}
-
-BOOL LLCubeMap::project(F32& v_min, F32& v_max, F32& h_min, F32& h_max,
- U8 side, LLVector3 dir[4]) const
-{
- v_min = h_min = RESOLUTION;
- v_max = h_max = 0;
-
- BOOL fully_outside = TRUE;
- for (U8 vtx = 0; vtx < 4; ++vtx)
- {
- F32 v_val, h_val;
- BOOL outside;
- BOOL consider = project(v_val, h_val, outside, side, dir[vtx]);
- if (!outside)
- fully_outside = FALSE;
- if (consider)
- {
- if (v_val < v_min) v_min = v_val;
- if (v_val > v_max) v_max = v_val;
- if (h_val < h_min) h_min = h_val;
- if (h_val > h_max) h_max = h_val;
- }
- }
-
- v_min = llmax(0.0f, v_min);
- v_max = llmin(RESOLUTION - epsilon, v_max);
- h_min = llmax(0.0f, h_min);
- h_max = llmin(RESOLUTION - epsilon, h_max);
-
- return !fully_outside;
-}
-
-
-void LLCubeMap::paintIn(LLVector3 dir[4], const LLColor4U& col)
-{
- LL_PROFILE_ZONE_SCOPED;
- F32 v_min, v_max, h_min, h_max;
- LLVector3 center = dir[0] + dir[1] + dir[2] + dir[3];
- center.normVec();
-
- for (U8 side = 0; side < 6; ++side)
- {
- if (!project(v_min, v_max, h_min, h_max, side, dir))
- continue;
-
- U8 *td = mRawImages[side]->getData();
-
- U16 v_minu = (U16) v_min;
- U16 v_maxu = (U16) (ceil(v_max) + 0.5);
- U16 h_minu = (U16) h_min;
- U16 h_maxu = (U16) (ceil(h_max) + 0.5);
-
- for (U16 v = v_minu; v < v_maxu; ++v)
- for (U16 h = h_minu; h < h_maxu; ++h)
- //for (U16 v = 0; v < RESOLUTION; ++v)
- // for (U16 h = 0; h < RESOLUTION; ++h)
- {
- const LLVector3 ray = map(side, v, h);
- if (ray * center > 0.999)
- {
- const U32 offset = (RESOLUTION * v + h) * 4;
- for (U8 cc = 0; cc < 3; ++cc)
- td[offset + cc] = U8((td[offset + cc] + col.mV[cc]) * 0.5);
- }
- }
- mImages[side]->setSubImage(mRawImages[side], 0, 0, RESOLUTION, RESOLUTION);
- }
-}
void LLCubeMap::destroyGL()
{
diff --git a/indra/llrender/llcubemap.h b/indra/llrender/llcubemap.h
index a01636d8d4..b9e081cea3 100644
--- a/indra/llrender/llcubemap.h
+++ b/indra/llrender/llcubemap.h
@@ -40,6 +40,17 @@ class LLCubeMap : public LLRefCount
public:
LLCubeMap(bool init_as_srgb);
void init(const std::vector<LLPointer<LLImageRaw> >& rawimages);
+
+ // initialize as an undefined cubemap at the given resolution
+ // used for render-to-cubemap operations
+ // avoids usage of LLImageRaw
+ void initReflectionMap(U32 resolution, U32 components = 3);
+
+ // init from environment map images
+ // Similar to init, but takes ownership of rawimages and makes this cubemap
+ // respect the resolution of rawimages
+ // Raw images must point to array of six square images that are all the same resolution
+ void initEnvironmentMap(const std::vector<LLPointer<LLImageRaw> >& rawimages);
void initGL();
void initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages);
void initGLData();
@@ -54,18 +65,15 @@ public:
void disableTexture(void);
void setMatrix(S32 stage);
void restoreMatrix();
- void setReflection (void);
- void finishPaint();
+ U32 getResolution() { return mImages[0].notNull() ? mImages[0]->getWidth(0) : 0; }
+
+ // generate mip maps for this Cube Map using GL
+ // NOTE: Cube Map MUST already be resident in VRAM
+ void generateMipMaps();
GLuint getGLName();
- LLVector3 map(U8 side, U16 v_val, U16 h_val) const;
- BOOL project(F32& v_val, F32& h_val, BOOL& outside,
- U8 side, const LLVector3& dir) const;
- BOOL project(F32& v_min, F32& v_max, F32& h_min, F32& h_max,
- U8 side, LLVector3 dir[4]) const;
- void paintIn(LLVector3 dir[4], const LLColor4U& col);
void destroyGL();
public:
diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp
new file mode 100644
index 0000000000..7d3a92237b
--- /dev/null
+++ b/indra/llrender/llcubemaparray.cpp
@@ -0,0 +1,177 @@
+/**
+ * @file llcubemaparray.cpp
+ * @brief LLCubeMap class implementation
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "llworkerthread.h"
+
+#include "llcubemaparray.h"
+
+#include "v4coloru.h"
+#include "v3math.h"
+#include "v3dmath.h"
+#include "m3math.h"
+#include "m4math.h"
+
+#include "llrender.h"
+#include "llglslshader.h"
+
+#include "llglheaders.h"
+
+//#pragma optimize("", off)
+
+// MUST match order of OpenGL face-layers
+GLenum LLCubeMapArray::sTargets[6] =
+{
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+};
+
+LLVector3 LLCubeMapArray::sLookVecs[6] =
+{
+ LLVector3(1, 0, 0),
+ LLVector3(-1, 0, 0),
+ LLVector3(0, 1, 0),
+ LLVector3(0, -1, 0),
+ LLVector3(0, 0, 1),
+ LLVector3(0, 0, -1)
+};
+
+LLVector3 LLCubeMapArray::sUpVecs[6] =
+{
+ LLVector3(0, -1, 0),
+ LLVector3(0, -1, 0),
+ LLVector3(0, 0, 1),
+ LLVector3(0, 0, -1),
+ LLVector3(0, -1, 0),
+ LLVector3(0, -1, 0)
+};
+
+LLVector3 LLCubeMapArray::sClipToCubeLookVecs[6] =
+{
+ LLVector3(0, 0, -1), //GOOD
+ LLVector3(0, 0, 1), //GOOD
+
+ LLVector3(1, 0, 0), // GOOD
+ LLVector3(1, 0, 0), // GOOD
+
+ LLVector3(1, 0, 0),
+ LLVector3(-1, 0, 0),
+};
+
+LLVector3 LLCubeMapArray::sClipToCubeUpVecs[6] =
+{
+ LLVector3(-1, 0, 0), //GOOD
+ LLVector3(1, 0, 0), //GOOD
+
+ LLVector3(0, 1, 0), // GOOD
+ LLVector3(0, -1, 0), // GOOD
+
+ LLVector3(0, 0, -1),
+ LLVector3(0, 0, 1)
+};
+
+LLCubeMapArray::LLCubeMapArray()
+ : mTextureStage(0)
+{
+
+}
+
+LLCubeMapArray::~LLCubeMapArray()
+{
+}
+
+void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, BOOL use_mips)
+{
+ U32 texname = 0;
+
+ LLImageGL::generateTextures(1, &texname);
+
+ mImage = new LLImageGL(resolution, resolution, components, use_mips);
+ mImage->setTexName(texname);
+ mImage->setTarget(sTargets[0], LLTexUnit::TT_CUBE_MAP_ARRAY);
+
+ mImage->setUseMipMaps(use_mips);
+ mImage->setHasMipMaps(use_mips);
+
+ bind(0);
+
+ U32 format = components == 4 ? GL_RGBA16F : GL_RGB16F;
+
+ U32 mip = 0;
+
+ while (resolution >= 1)
+ {
+ glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, format, resolution, resolution, count * 6, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+ if (!use_mips)
+ {
+ break;
+ }
+ resolution /= 2;
+ ++mip;
+ }
+
+ mImage->setAddressMode(LLTexUnit::TAM_CLAMP);
+
+ if (use_mips)
+ {
+ mImage->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+ //glGenerateMipmap(GL_TEXTURE_CUBE_MAP_ARRAY); // <=== latest AMD drivers do not appreciate this method of allocating mipmaps
+ }
+ else
+ {
+ mImage->setFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ unbind();
+}
+
+void LLCubeMapArray::bind(S32 stage)
+{
+ mTextureStage = stage;
+ gGL.getTexUnit(stage)->bindManual(LLTexUnit::TT_CUBE_MAP_ARRAY, getGLName(), mImage->getUseMipMaps());
+}
+
+void LLCubeMapArray::unbind()
+{
+ gGL.getTexUnit(mTextureStage)->unbind(LLTexUnit::TT_CUBE_MAP_ARRAY);
+ mTextureStage = -1;
+}
+
+GLuint LLCubeMapArray::getGLName()
+{
+ return mImage->getTexName();
+}
+
+void LLCubeMapArray::destroyGL()
+{
+ mImage = NULL;
+}
diff --git a/indra/llrender/llcubemaparray.h b/indra/llrender/llcubemaparray.h
new file mode 100644
index 0000000000..19c86278a1
--- /dev/null
+++ b/indra/llrender/llcubemaparray.h
@@ -0,0 +1,68 @@
+/**
+ * @file llcubemaparray.h
+ * @brief LLCubeMap class definition
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#pragma once
+
+#include "llgl.h"
+
+#include <vector>
+
+class LLVector3;
+
+class LLCubeMapArray : public LLRefCount
+{
+public:
+ LLCubeMapArray();
+
+ static GLenum sTargets[6];
+
+ // look and up vectors for each cube face (agent space)
+ static LLVector3 sLookVecs[6];
+ static LLVector3 sUpVecs[6];
+
+ // look and up vectors for each cube face (clip space)
+ static LLVector3 sClipToCubeLookVecs[6];
+ static LLVector3 sClipToCubeUpVecs[6];
+
+ // allocate a cube map array
+ // res - resolution of each cube face
+ // components - number of components per pixel
+ // count - number of cube maps in the array
+ // use_mips - if TRUE, mipmaps will be allocated for this cube map array and anisotropic filtering will be used
+ void allocate(U32 res, U32 components, U32 count, BOOL use_mips = TRUE);
+ void bind(S32 stage);
+ void unbind();
+
+ GLuint getGLName();
+
+ void destroyGL();
+
+protected:
+ friend class LLTexUnit;
+ ~LLCubeMapArray();
+ LLPointer<LLImageGL> mImage;
+ S32 mTextureStage;
+};
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 193cfa64b8..ae408dae4f 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -86,30 +86,73 @@ void APIENTRY gl_debug_callback(GLenum source,
const GLchar* message,
GLvoid* userParam)
{
- if (severity != GL_DEBUG_SEVERITY_HIGH_ARB &&
- severity != GL_DEBUG_SEVERITY_MEDIUM_ARB &&
- severity != GL_DEBUG_SEVERITY_LOW_ARB)
+ /*if (severity != GL_DEBUG_SEVERITY_HIGH &&
+ severity != GL_DEBUG_SEVERITY_MEDIUM &&
+ severity != GL_DEBUG_SEVERITY_LOW
+ )
{ //suppress out-of-spec messages sent by nvidia driver (mostly vertexbuffer hints)
return;
+ }*/
+
+ // list of messages to suppress
+ const char* suppress[] =
+ {
+ "Buffer detailed info:",
+ "Program undefined behavior warning: The current GL state uses a sampler (0) that has depth comparisons enabled"
+ };
+
+ for (const char* msg : suppress)
+ {
+ if (strncmp(msg, message, strlen(msg)) == 0)
+ {
+ return;
+ }
}
- if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
- {
- LL_WARNS() << "----- GL ERROR --------" << LL_ENDL;
- }
- else
- {
- LL_WARNS() << "----- GL WARNING -------" << LL_ENDL;
- }
- LL_WARNS() << "Type: " << std::hex << type << LL_ENDL;
- LL_WARNS() << "ID: " << std::hex << id << LL_ENDL;
- LL_WARNS() << "Severity: " << std::hex << severity << LL_ENDL;
- LL_WARNS() << "Message: " << message << LL_ENDL;
- LL_WARNS() << "-----------------------" << LL_ENDL;
- if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
- {
- LL_ERRS() << "Halting on GL Error" << LL_ENDL;
- }
+ if (severity == GL_DEBUG_SEVERITY_HIGH)
+ {
+ LL_WARNS() << "----- GL ERROR --------" << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS() << "----- GL WARNING -------" << LL_ENDL;
+ }
+ LL_WARNS() << "Type: " << std::hex << type << LL_ENDL;
+ LL_WARNS() << "ID: " << std::hex << id << LL_ENDL;
+ LL_WARNS() << "Severity: " << std::hex << severity << LL_ENDL;
+ LL_WARNS() << "Message: " << message << LL_ENDL;
+ LL_WARNS() << "-----------------------" << LL_ENDL;
+
+ GLint vao = 0;
+ glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &vao);
+ GLint vbo = 0;
+ glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &vbo);
+ GLint vbo_size = 0;
+ if (vbo != 0)
+ {
+ glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &vbo_size);
+ }
+ GLint ibo = 0;
+ glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &ibo);
+ GLint ibo_size = 0;
+ if (ibo != 0)
+ {
+ glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &ibo_size);
+ }
+ GLint ubo = 0;
+ glGetIntegerv(GL_UNIFORM_BUFFER_BINDING, &ubo);
+ GLint ubo_size = 0;
+ GLint ubo_immutable = 0;
+ if (ubo != 0)
+ {
+ glGetBufferParameteriv(GL_UNIFORM_BUFFER, GL_BUFFER_SIZE, &ubo_size);
+ glGetBufferParameteriv(GL_UNIFORM_BUFFER, GL_BUFFER_IMMUTABLE_STORAGE, &ubo_immutable);
+ }
+
+ if (severity == GL_DEBUG_SEVERITY_HIGH)
+ {
+ LL_ERRS() << "Halting on GL Error" << LL_ENDL;
+ }
}
#endif
@@ -159,246 +202,770 @@ std::list<LLGLUpdate*> LLGLUpdate::sGLQ;
#if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS
#if LL_WINDOWS
-PFNGLGETSTRINGIPROC glGetStringi = NULL;
-#endif
+// WGL_ARB_create_context
+PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = nullptr;
+
+// WGL_AMD_gpu_association
+PFNWGLGETGPUIDSAMDPROC wglGetGPUIDsAMD = nullptr;
+PFNWGLGETGPUINFOAMDPROC wglGetGPUInfoAMD = nullptr;
+PFNWGLGETCONTEXTGPUIDAMDPROC wglGetContextGPUIDAMD = nullptr;
+PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC wglCreateAssociatedContextAMD = nullptr;
+PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC wglCreateAssociatedContextAttribsAMD = nullptr;
+PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC wglDeleteAssociatedContextAMD = nullptr;
+PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC wglMakeAssociatedContextCurrentAMD = nullptr;
+PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC wglGetCurrentAssociatedContextAMD = nullptr;
+PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC wglBlitContextFramebufferAMD = nullptr;
+
+// WGL_EXT_swap_control
+PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = nullptr;
+PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT = nullptr;
-// vertex blending prototypes
-PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB = NULL;
-PFNGLVERTEXBLENDARBPROC glVertexBlendARB = NULL;
-PFNGLWEIGHTFVARBPROC glWeightfvARB = NULL;
-
-// Vertex buffer object prototypes
-PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;
-PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL;
-PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;
-PFNGLISBUFFERARBPROC glIsBufferARB = NULL;
-PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL;
-PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB = NULL;
-PFNGLGETBUFFERSUBDATAARBPROC glGetBufferSubDataARB = NULL;
-PFNGLMAPBUFFERARBPROC glMapBufferARB = NULL;
-PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL;
-PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB = NULL;
-PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB = NULL;
-
-//GL_ARB_vertex_array_object
-PFNGLBINDVERTEXARRAYPROC glBindVertexArray = NULL;
-PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays = NULL;
-PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = NULL;
-PFNGLISVERTEXARRAYPROC glIsVertexArray = NULL;
-
-// GL_ARB_map_buffer_range
-PFNGLMAPBUFFERRANGEPROC glMapBufferRange = NULL;
-PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange = NULL;
-
-// GL_ARB_sync
-PFNGLFENCESYNCPROC glFenceSync = NULL;
-PFNGLISSYNCPROC glIsSync = NULL;
-PFNGLDELETESYNCPROC glDeleteSync = NULL;
-PFNGLCLIENTWAITSYNCPROC glClientWaitSync = NULL;
-PFNGLWAITSYNCPROC glWaitSync = NULL;
-PFNGLGETINTEGER64VPROC glGetInteger64v = NULL;
-PFNGLGETSYNCIVPROC glGetSynciv = NULL;
-
-// GL_APPLE_flush_buffer_range
-PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE = NULL;
-PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE = NULL;
-
-// GL_ARB_occlusion_query
-PFNGLGENQUERIESARBPROC glGenQueriesARB = NULL;
-PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB = NULL;
-PFNGLISQUERYARBPROC glIsQueryARB = NULL;
-PFNGLBEGINQUERYARBPROC glBeginQueryARB = NULL;
-PFNGLENDQUERYARBPROC glEndQueryARB = NULL;
-PFNGLGETQUERYIVARBPROC glGetQueryivARB = NULL;
-PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB = NULL;
-PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB = NULL;
-
-// GL_ARB_timer_query
-PFNGLQUERYCOUNTERPROC glQueryCounter = NULL;
-PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v = NULL;
-PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v = NULL;
-
-// GL_ARB_point_parameters
-PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB = NULL;
-PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB = NULL;
-
-// GL_ARB_framebuffer_object
-PFNGLISRENDERBUFFERPROC glIsRenderbuffer = NULL;
-PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer = NULL;
-PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers = NULL;
-PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers = NULL;
-PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage = NULL;
-PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv = NULL;
-PFNGLISFRAMEBUFFERPROC glIsFramebuffer = NULL;
-PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = NULL;
-PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers = NULL;
-PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers = NULL;
-PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus = NULL;
-PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D = NULL;
-PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D = NULL;
-PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D = NULL;
-PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer = NULL;
-PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv = NULL;
-PFNGLGENERATEMIPMAPPROC glGenerateMipmap = NULL;
-PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer = NULL;
-PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample = NULL;
-PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer = NULL;
-
-//GL_ARB_texture_multisample
-PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample = NULL;
-PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample = NULL;
-PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv = NULL;
-PFNGLSAMPLEMASKIPROC glSampleMaski = NULL;
-
-//transform feedback (4.0 core)
-PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback = NULL;
-PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback = NULL;
-PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings = NULL;
-PFNGLBINDBUFFERRANGEPROC glBindBufferRange = NULL;
-PFNGLBINDBUFFERBASEPROC glBindBufferBase = NULL;
-
-//GL_ARB_debug_output
-PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB = NULL;
-PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB = NULL;
-PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB = NULL;
-PFNGLGETDEBUGMESSAGELOGARBPROC glGetDebugMessageLogARB = NULL;
-
-// GL_EXT_blend_func_separate
-PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL;
-
-// GL_ARB_draw_buffers
-PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB = NULL;
-
-//shader object prototypes
-PFNGLDELETEOBJECTARBPROC glDeleteObjectARB = NULL;
-PFNGLGETHANDLEARBPROC glGetHandleARB = NULL;
-PFNGLDETACHOBJECTARBPROC glDetachObjectARB = NULL;
-PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB = NULL;
-PFNGLSHADERSOURCEARBPROC glShaderSourceARB = NULL;
-PFNGLCOMPILESHADERARBPROC glCompileShaderARB = NULL;
-PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB = NULL;
-PFNGLATTACHOBJECTARBPROC glAttachObjectARB = NULL;
-PFNGLLINKPROGRAMARBPROC glLinkProgramARB = NULL;
-PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB = NULL;
-PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB = NULL;
-PFNGLUNIFORM1FARBPROC glUniform1fARB = NULL;
-PFNGLUNIFORM2FARBPROC glUniform2fARB = NULL;
-PFNGLUNIFORM3FARBPROC glUniform3fARB = NULL;
-PFNGLUNIFORM4FARBPROC glUniform4fARB = NULL;
-PFNGLUNIFORM1IARBPROC glUniform1iARB = NULL;
-PFNGLUNIFORM2IARBPROC glUniform2iARB = NULL;
-PFNGLUNIFORM3IARBPROC glUniform3iARB = NULL;
-PFNGLUNIFORM4IARBPROC glUniform4iARB = NULL;
-PFNGLUNIFORM1FVARBPROC glUniform1fvARB = NULL;
-PFNGLUNIFORM2FVARBPROC glUniform2fvARB = NULL;
-PFNGLUNIFORM3FVARBPROC glUniform3fvARB = NULL;
-PFNGLUNIFORM4FVARBPROC glUniform4fvARB = NULL;
-PFNGLUNIFORM1IVARBPROC glUniform1ivARB = NULL;
-PFNGLUNIFORM2IVARBPROC glUniform2ivARB = NULL;
-PFNGLUNIFORM3IVARBPROC glUniform3ivARB = NULL;
-PFNGLUNIFORM4IVARBPROC glUniform4ivARB = NULL;
-PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB = NULL;
-PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB = NULL;
-PFNGLUNIFORMMATRIX3X4FVPROC glUniformMatrix3x4fv = NULL;
-PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB = NULL;
-PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB = NULL;
-PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB = NULL;
-PFNGLGETINFOLOGARBPROC glGetInfoLogARB = NULL;
-PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB = NULL;
-PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB = NULL;
-PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB = NULL;
-PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB = NULL;
-PFNGLGETUNIFORMIVARBPROC glGetUniformivARB = NULL;
-PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB = NULL;
-PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer = NULL;
-
-#if LL_WINDOWS
-PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
#endif
-// vertex shader prototypes
-#if LL_LINUX
-PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB = NULL;
-PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB = NULL;
-PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB = NULL;
-PFNGLVERTEXATTRIB1FVARBPROC glVertexAttrib1fvARB = NULL;
-PFNGLVERTEXATTRIB1SARBPROC glVertexAttrib1sARB = NULL;
-PFNGLVERTEXATTRIB1SVARBPROC glVertexAttrib1svARB = NULL;
-PFNGLVERTEXATTRIB2DARBPROC glVertexAttrib2dARB = NULL;
-PFNGLVERTEXATTRIB2DVARBPROC glVertexAttrib2dvARB = NULL;
-PFNGLVERTEXATTRIB2FARBPROC glVertexAttrib2fARB = NULL;
-PFNGLVERTEXATTRIB2FVARBPROC glVertexAttrib2fvARB = NULL;
-PFNGLVERTEXATTRIB2SARBPROC glVertexAttrib2sARB = NULL;
-PFNGLVERTEXATTRIB2SVARBPROC glVertexAttrib2svARB = NULL;
-PFNGLVERTEXATTRIB3DARBPROC glVertexAttrib3dARB = NULL;
-PFNGLVERTEXATTRIB3DVARBPROC glVertexAttrib3dvARB = NULL;
-PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB = NULL;
-PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB = NULL;
-PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB = NULL;
-PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB = NULL;
-#endif // LL_LINUX
-PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB = NULL;
-PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB = NULL;
-PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB = NULL;
-PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB = NULL;
-PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB = NULL;
-PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB = NULL;
-PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB = NULL;
-#if LL_LINUX
-PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB = NULL;
-PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB = NULL;
-PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB = NULL;
-PFNGLVERTEXATTRIB4FARBPROC glVertexAttrib4fARB = NULL;
-PFNGLVERTEXATTRIB4FVARBPROC glVertexAttrib4fvARB = NULL;
-PFNGLVERTEXATTRIB4IVARBPROC glVertexAttrib4ivARB = NULL;
-PFNGLVERTEXATTRIB4SARBPROC glVertexAttrib4sARB = NULL;
-PFNGLVERTEXATTRIB4SVARBPROC glVertexAttrib4svARB = NULL;
-PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB = NULL;
-PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB = NULL;
-PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB = NULL;
-PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB = NULL;
-PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB = NULL;
-PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB = NULL;
-PFNGLPROGRAMSTRINGARBPROC glProgramStringARB = NULL;
-PFNGLBINDPROGRAMARBPROC glBindProgramARB = NULL;
-PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB = NULL;
-PFNGLGENPROGRAMSARBPROC glGenProgramsARB = NULL;
-PFNGLPROGRAMENVPARAMETER4DARBPROC glProgramEnvParameter4dARB = NULL;
-PFNGLPROGRAMENVPARAMETER4DVARBPROC glProgramEnvParameter4dvARB = NULL;
-PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB = NULL;
-PFNGLPROGRAMENVPARAMETER4FVARBPROC glProgramEnvParameter4fvARB = NULL;
-PFNGLPROGRAMLOCALPARAMETER4DARBPROC glProgramLocalParameter4dARB = NULL;
-PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glProgramLocalParameter4dvARB = NULL;
-PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB = NULL;
-PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB = NULL;
-PFNGLGETPROGRAMENVPARAMETERDVARBPROC glGetProgramEnvParameterdvARB = NULL;
-PFNGLGETPROGRAMENVPARAMETERFVARBPROC glGetProgramEnvParameterfvARB = NULL;
-PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glGetProgramLocalParameterdvARB = NULL;
-PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glGetProgramLocalParameterfvARB = NULL;
-PFNGLGETPROGRAMIVARBPROC glGetProgramivARB = NULL;
-PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB = NULL;
-PFNGLGETVERTEXATTRIBDVARBPROC glGetVertexAttribdvARB = NULL;
-PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB = NULL;
-PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB = NULL;
-PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB = NULL;
-PFNGLISPROGRAMARBPROC glIsProgramARB = NULL;
-#endif // LL_LINUX
-PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB = NULL;
-PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB = NULL;
-PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB = NULL;
-
-#if LL_WINDOWS
-PFNWGLGETGPUIDSAMDPROC wglGetGPUIDsAMD = NULL;
-PFNWGLGETGPUINFOAMDPROC wglGetGPUInfoAMD = NULL;
-PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;
-#endif
+// GL_VERSION_1_2
+//PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements = nullptr;
+//PFNGLTEXIMAGE3DPROC glTexImage3D = nullptr;
+//PFNGLTEXSUBIMAGE3DPROC glTexSubImage3D = nullptr;
+//PFNGLCOPYTEXSUBIMAGE3DPROC glCopyTexSubImage3D = nullptr;
+
+// GL_VERSION_1_3
+PFNGLACTIVETEXTUREPROC glActiveTexture = nullptr;
+PFNGLSAMPLECOVERAGEPROC glSampleCoverage = nullptr;
+PFNGLCOMPRESSEDTEXIMAGE3DPROC glCompressedTexImage3D = nullptr;
+PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D = nullptr;
+PFNGLCOMPRESSEDTEXIMAGE1DPROC glCompressedTexImage1D = nullptr;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glCompressedTexSubImage3D = nullptr;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glCompressedTexSubImage2D = nullptr;
+PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glCompressedTexSubImage1D = nullptr;
+PFNGLGETCOMPRESSEDTEXIMAGEPROC glGetCompressedTexImage = nullptr;
+PFNGLCLIENTACTIVETEXTUREPROC glClientActiveTexture = nullptr;
+PFNGLMULTITEXCOORD1DPROC glMultiTexCoord1d = nullptr;
+PFNGLMULTITEXCOORD1DVPROC glMultiTexCoord1dv = nullptr;
+PFNGLMULTITEXCOORD1FPROC glMultiTexCoord1f = nullptr;
+PFNGLMULTITEXCOORD1FVPROC glMultiTexCoord1fv = nullptr;
+PFNGLMULTITEXCOORD1IPROC glMultiTexCoord1i = nullptr;
+PFNGLMULTITEXCOORD1IVPROC glMultiTexCoord1iv = nullptr;
+PFNGLMULTITEXCOORD1SPROC glMultiTexCoord1s = nullptr;
+PFNGLMULTITEXCOORD1SVPROC glMultiTexCoord1sv = nullptr;
+PFNGLMULTITEXCOORD2DPROC glMultiTexCoord2d = nullptr;
+PFNGLMULTITEXCOORD2DVPROC glMultiTexCoord2dv = nullptr;
+PFNGLMULTITEXCOORD2FPROC glMultiTexCoord2f = nullptr;
+PFNGLMULTITEXCOORD2FVPROC glMultiTexCoord2fv = nullptr;
+PFNGLMULTITEXCOORD2IPROC glMultiTexCoord2i = nullptr;
+PFNGLMULTITEXCOORD2IVPROC glMultiTexCoord2iv = nullptr;
+PFNGLMULTITEXCOORD2SPROC glMultiTexCoord2s = nullptr;
+PFNGLMULTITEXCOORD2SVPROC glMultiTexCoord2sv = nullptr;
+PFNGLMULTITEXCOORD3DPROC glMultiTexCoord3d = nullptr;
+PFNGLMULTITEXCOORD3DVPROC glMultiTexCoord3dv = nullptr;
+PFNGLMULTITEXCOORD3FPROC glMultiTexCoord3f = nullptr;
+PFNGLMULTITEXCOORD3FVPROC glMultiTexCoord3fv = nullptr;
+PFNGLMULTITEXCOORD3IPROC glMultiTexCoord3i = nullptr;
+PFNGLMULTITEXCOORD3IVPROC glMultiTexCoord3iv = nullptr;
+PFNGLMULTITEXCOORD3SPROC glMultiTexCoord3s = nullptr;
+PFNGLMULTITEXCOORD3SVPROC glMultiTexCoord3sv = nullptr;
+PFNGLMULTITEXCOORD4DPROC glMultiTexCoord4d = nullptr;
+PFNGLMULTITEXCOORD4DVPROC glMultiTexCoord4dv = nullptr;
+PFNGLMULTITEXCOORD4FPROC glMultiTexCoord4f = nullptr;
+PFNGLMULTITEXCOORD4FVPROC glMultiTexCoord4fv = nullptr;
+PFNGLMULTITEXCOORD4IPROC glMultiTexCoord4i = nullptr;
+PFNGLMULTITEXCOORD4IVPROC glMultiTexCoord4iv = nullptr;
+PFNGLMULTITEXCOORD4SPROC glMultiTexCoord4s = nullptr;
+PFNGLMULTITEXCOORD4SVPROC glMultiTexCoord4sv = nullptr;
+PFNGLLOADTRANSPOSEMATRIXFPROC glLoadTransposeMatrixf = nullptr;
+PFNGLLOADTRANSPOSEMATRIXDPROC glLoadTransposeMatrixd = nullptr;
+PFNGLMULTTRANSPOSEMATRIXFPROC glMultTransposeMatrixf = nullptr;
+PFNGLMULTTRANSPOSEMATRIXDPROC glMultTransposeMatrixd = nullptr;
+
+// GL_VERSION_1_4
+PFNGLBLENDFUNCSEPARATEPROC glBlendFuncSeparate = nullptr;
+PFNGLMULTIDRAWARRAYSPROC glMultiDrawArrays = nullptr;
+PFNGLMULTIDRAWELEMENTSPROC glMultiDrawElements = nullptr;
+PFNGLPOINTPARAMETERFPROC glPointParameterf = nullptr;
+PFNGLPOINTPARAMETERFVPROC glPointParameterfv = nullptr;
+PFNGLPOINTPARAMETERIPROC glPointParameteri = nullptr;
+PFNGLPOINTPARAMETERIVPROC glPointParameteriv = nullptr;
+PFNGLFOGCOORDFPROC glFogCoordf = nullptr;
+PFNGLFOGCOORDFVPROC glFogCoordfv = nullptr;
+PFNGLFOGCOORDDPROC glFogCoordd = nullptr;
+PFNGLFOGCOORDDVPROC glFogCoorddv = nullptr;
+PFNGLFOGCOORDPOINTERPROC glFogCoordPointer = nullptr;
+PFNGLSECONDARYCOLOR3BPROC glSecondaryColor3b = nullptr;
+PFNGLSECONDARYCOLOR3BVPROC glSecondaryColor3bv = nullptr;
+PFNGLSECONDARYCOLOR3DPROC glSecondaryColor3d = nullptr;
+PFNGLSECONDARYCOLOR3DVPROC glSecondaryColor3dv = nullptr;
+PFNGLSECONDARYCOLOR3FPROC glSecondaryColor3f = nullptr;
+PFNGLSECONDARYCOLOR3FVPROC glSecondaryColor3fv = nullptr;
+PFNGLSECONDARYCOLOR3IPROC glSecondaryColor3i = nullptr;
+PFNGLSECONDARYCOLOR3IVPROC glSecondaryColor3iv = nullptr;
+PFNGLSECONDARYCOLOR3SPROC glSecondaryColor3s = nullptr;
+PFNGLSECONDARYCOLOR3SVPROC glSecondaryColor3sv = nullptr;
+PFNGLSECONDARYCOLOR3UBPROC glSecondaryColor3ub = nullptr;
+PFNGLSECONDARYCOLOR3UBVPROC glSecondaryColor3ubv = nullptr;
+PFNGLSECONDARYCOLOR3UIPROC glSecondaryColor3ui = nullptr;
+PFNGLSECONDARYCOLOR3UIVPROC glSecondaryColor3uiv = nullptr;
+PFNGLSECONDARYCOLOR3USPROC glSecondaryColor3us = nullptr;
+PFNGLSECONDARYCOLOR3USVPROC glSecondaryColor3usv = nullptr;
+PFNGLSECONDARYCOLORPOINTERPROC glSecondaryColorPointer = nullptr;
+PFNGLWINDOWPOS2DPROC glWindowPos2d = nullptr;
+PFNGLWINDOWPOS2DVPROC glWindowPos2dv = nullptr;
+PFNGLWINDOWPOS2FPROC glWindowPos2f = nullptr;
+PFNGLWINDOWPOS2FVPROC glWindowPos2fv = nullptr;
+PFNGLWINDOWPOS2IPROC glWindowPos2i = nullptr;
+PFNGLWINDOWPOS2IVPROC glWindowPos2iv = nullptr;
+PFNGLWINDOWPOS2SPROC glWindowPos2s = nullptr;
+PFNGLWINDOWPOS2SVPROC glWindowPos2sv = nullptr;
+PFNGLWINDOWPOS3DPROC glWindowPos3d = nullptr;
+PFNGLWINDOWPOS3DVPROC glWindowPos3dv = nullptr;
+PFNGLWINDOWPOS3FPROC glWindowPos3f = nullptr;
+PFNGLWINDOWPOS3FVPROC glWindowPos3fv = nullptr;
+PFNGLWINDOWPOS3IPROC glWindowPos3i = nullptr;
+PFNGLWINDOWPOS3IVPROC glWindowPos3iv = nullptr;
+PFNGLWINDOWPOS3SPROC glWindowPos3s = nullptr;
+PFNGLWINDOWPOS3SVPROC glWindowPos3sv = nullptr;
+
+// GL_VERSION_1_5
+PFNGLGENQUERIESPROC glGenQueries = nullptr;
+PFNGLDELETEQUERIESPROC glDeleteQueries = nullptr;
+PFNGLISQUERYPROC glIsQuery = nullptr;
+PFNGLBEGINQUERYPROC glBeginQuery = nullptr;
+PFNGLENDQUERYPROC glEndQuery = nullptr;
+PFNGLGETQUERYIVPROC glGetQueryiv = nullptr;
+PFNGLGETQUERYOBJECTIVPROC glGetQueryObjectiv = nullptr;
+PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv = nullptr;
+PFNGLBINDBUFFERPROC glBindBuffer = nullptr;
+PFNGLDELETEBUFFERSPROC glDeleteBuffers = nullptr;
+PFNGLGENBUFFERSPROC glGenBuffers = nullptr;
+PFNGLISBUFFERPROC glIsBuffer = nullptr;
+PFNGLBUFFERDATAPROC glBufferData = nullptr;
+PFNGLBUFFERSUBDATAPROC glBufferSubData = nullptr;
+PFNGLGETBUFFERSUBDATAPROC glGetBufferSubData = nullptr;
+PFNGLMAPBUFFERPROC glMapBuffer = nullptr;
+PFNGLUNMAPBUFFERPROC glUnmapBuffer = nullptr;
+PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv = nullptr;
+PFNGLGETBUFFERPOINTERVPROC glGetBufferPointerv = nullptr;
+
+// GL_VERSION_2_0
+PFNGLBLENDEQUATIONSEPARATEPROC glBlendEquationSeparate = nullptr;
+PFNGLDRAWBUFFERSPROC glDrawBuffers = nullptr;
+PFNGLSTENCILOPSEPARATEPROC glStencilOpSeparate = nullptr;
+PFNGLSTENCILFUNCSEPARATEPROC glStencilFuncSeparate = nullptr;
+PFNGLSTENCILMASKSEPARATEPROC glStencilMaskSeparate = nullptr;
+PFNGLATTACHSHADERPROC glAttachShader = nullptr;
+PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation = nullptr;
+PFNGLCOMPILESHADERPROC glCompileShader = nullptr;
+PFNGLCREATEPROGRAMPROC glCreateProgram = nullptr;
+PFNGLCREATESHADERPROC glCreateShader = nullptr;
+PFNGLDELETEPROGRAMPROC glDeleteProgram = nullptr;
+PFNGLDELETESHADERPROC glDeleteShader = nullptr;
+PFNGLDETACHSHADERPROC glDetachShader = nullptr;
+PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray = nullptr;
+PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = nullptr;
+PFNGLGETACTIVEATTRIBPROC glGetActiveAttrib = nullptr;
+PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform = nullptr;
+PFNGLGETATTACHEDSHADERSPROC glGetAttachedShaders = nullptr;
+PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation = nullptr;
+PFNGLGETPROGRAMIVPROC glGetProgramiv = nullptr;
+PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = nullptr;
+PFNGLGETSHADERIVPROC glGetShaderiv = nullptr;
+PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog = nullptr;
+PFNGLGETSHADERSOURCEPROC glGetShaderSource = nullptr;
+PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = nullptr;
+PFNGLGETUNIFORMFVPROC glGetUniformfv = nullptr;
+PFNGLGETUNIFORMIVPROC glGetUniformiv = nullptr;
+PFNGLGETVERTEXATTRIBDVPROC glGetVertexAttribdv = nullptr;
+PFNGLGETVERTEXATTRIBFVPROC glGetVertexAttribfv = nullptr;
+PFNGLGETVERTEXATTRIBIVPROC glGetVertexAttribiv = nullptr;
+PFNGLGETVERTEXATTRIBPOINTERVPROC glGetVertexAttribPointerv = nullptr;
+PFNGLISPROGRAMPROC glIsProgram = nullptr;
+PFNGLISSHADERPROC glIsShader = nullptr;
+PFNGLLINKPROGRAMPROC glLinkProgram = nullptr;
+PFNGLSHADERSOURCEPROC glShaderSource = nullptr;
+PFNGLUSEPROGRAMPROC glUseProgram = nullptr;
+PFNGLUNIFORM1FPROC glUniform1f = nullptr;
+PFNGLUNIFORM2FPROC glUniform2f = nullptr;
+PFNGLUNIFORM3FPROC glUniform3f = nullptr;
+PFNGLUNIFORM4FPROC glUniform4f = nullptr;
+PFNGLUNIFORM1IPROC glUniform1i = nullptr;
+PFNGLUNIFORM2IPROC glUniform2i = nullptr;
+PFNGLUNIFORM3IPROC glUniform3i = nullptr;
+PFNGLUNIFORM4IPROC glUniform4i = nullptr;
+PFNGLUNIFORM1FVPROC glUniform1fv = nullptr;
+PFNGLUNIFORM2FVPROC glUniform2fv = nullptr;
+PFNGLUNIFORM3FVPROC glUniform3fv = nullptr;
+PFNGLUNIFORM4FVPROC glUniform4fv = nullptr;
+PFNGLUNIFORM1IVPROC glUniform1iv = nullptr;
+PFNGLUNIFORM2IVPROC glUniform2iv = nullptr;
+PFNGLUNIFORM3IVPROC glUniform3iv = nullptr;
+PFNGLUNIFORM4IVPROC glUniform4iv = nullptr;
+PFNGLUNIFORMMATRIX2FVPROC glUniformMatrix2fv = nullptr;
+PFNGLUNIFORMMATRIX3FVPROC glUniformMatrix3fv = nullptr;
+PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv = nullptr;
+PFNGLVALIDATEPROGRAMPROC glValidateProgram = nullptr;
+PFNGLVERTEXATTRIB1DPROC glVertexAttrib1d = nullptr;
+PFNGLVERTEXATTRIB1DVPROC glVertexAttrib1dv = nullptr;
+PFNGLVERTEXATTRIB1FPROC glVertexAttrib1f = nullptr;
+PFNGLVERTEXATTRIB1FVPROC glVertexAttrib1fv = nullptr;
+PFNGLVERTEXATTRIB1SPROC glVertexAttrib1s = nullptr;
+PFNGLVERTEXATTRIB1SVPROC glVertexAttrib1sv = nullptr;
+PFNGLVERTEXATTRIB2DPROC glVertexAttrib2d = nullptr;
+PFNGLVERTEXATTRIB2DVPROC glVertexAttrib2dv = nullptr;
+PFNGLVERTEXATTRIB2FPROC glVertexAttrib2f = nullptr;
+PFNGLVERTEXATTRIB2FVPROC glVertexAttrib2fv = nullptr;
+PFNGLVERTEXATTRIB2SPROC glVertexAttrib2s = nullptr;
+PFNGLVERTEXATTRIB2SVPROC glVertexAttrib2sv = nullptr;
+PFNGLVERTEXATTRIB3DPROC glVertexAttrib3d = nullptr;
+PFNGLVERTEXATTRIB3DVPROC glVertexAttrib3dv = nullptr;
+PFNGLVERTEXATTRIB3FPROC glVertexAttrib3f = nullptr;
+PFNGLVERTEXATTRIB3FVPROC glVertexAttrib3fv = nullptr;
+PFNGLVERTEXATTRIB3SPROC glVertexAttrib3s = nullptr;
+PFNGLVERTEXATTRIB3SVPROC glVertexAttrib3sv = nullptr;
+PFNGLVERTEXATTRIB4NBVPROC glVertexAttrib4Nbv = nullptr;
+PFNGLVERTEXATTRIB4NIVPROC glVertexAttrib4Niv = nullptr;
+PFNGLVERTEXATTRIB4NSVPROC glVertexAttrib4Nsv = nullptr;
+PFNGLVERTEXATTRIB4NUBPROC glVertexAttrib4Nub = nullptr;
+PFNGLVERTEXATTRIB4NUBVPROC glVertexAttrib4Nubv = nullptr;
+PFNGLVERTEXATTRIB4NUIVPROC glVertexAttrib4Nuiv = nullptr;
+PFNGLVERTEXATTRIB4NUSVPROC glVertexAttrib4Nusv = nullptr;
+PFNGLVERTEXATTRIB4BVPROC glVertexAttrib4bv = nullptr;
+PFNGLVERTEXATTRIB4DPROC glVertexAttrib4d = nullptr;
+PFNGLVERTEXATTRIB4DVPROC glVertexAttrib4dv = nullptr;
+PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f = nullptr;
+PFNGLVERTEXATTRIB4FVPROC glVertexAttrib4fv = nullptr;
+PFNGLVERTEXATTRIB4IVPROC glVertexAttrib4iv = nullptr;
+PFNGLVERTEXATTRIB4SPROC glVertexAttrib4s = nullptr;
+PFNGLVERTEXATTRIB4SVPROC glVertexAttrib4sv = nullptr;
+PFNGLVERTEXATTRIB4UBVPROC glVertexAttrib4ubv = nullptr;
+PFNGLVERTEXATTRIB4UIVPROC glVertexAttrib4uiv = nullptr;
+PFNGLVERTEXATTRIB4USVPROC glVertexAttrib4usv = nullptr;
+PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = nullptr;
+
+// GL_VERSION_2_1
+PFNGLUNIFORMMATRIX2X3FVPROC glUniformMatrix2x3fv = nullptr;
+PFNGLUNIFORMMATRIX3X2FVPROC glUniformMatrix3x2fv = nullptr;
+PFNGLUNIFORMMATRIX2X4FVPROC glUniformMatrix2x4fv = nullptr;
+PFNGLUNIFORMMATRIX4X2FVPROC glUniformMatrix4x2fv = nullptr;
+PFNGLUNIFORMMATRIX3X4FVPROC glUniformMatrix3x4fv = nullptr;
+PFNGLUNIFORMMATRIX4X3FVPROC glUniformMatrix4x3fv = nullptr;
+
+// GL_VERSION_3_0
+PFNGLCOLORMASKIPROC glColorMaski = nullptr;
+PFNGLGETBOOLEANI_VPROC glGetBooleani_v = nullptr;
+PFNGLGETINTEGERI_VPROC glGetIntegeri_v = nullptr;
+PFNGLENABLEIPROC glEnablei = nullptr;
+PFNGLDISABLEIPROC glDisablei = nullptr;
+PFNGLISENABLEDIPROC glIsEnabledi = nullptr;
+PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback = nullptr;
+PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback = nullptr;
+PFNGLBINDBUFFERRANGEPROC glBindBufferRange = nullptr;
+PFNGLBINDBUFFERBASEPROC glBindBufferBase = nullptr;
+PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings = nullptr;
+PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glGetTransformFeedbackVarying = nullptr;
+PFNGLCLAMPCOLORPROC glClampColor = nullptr;
+PFNGLBEGINCONDITIONALRENDERPROC glBeginConditionalRender = nullptr;
+PFNGLENDCONDITIONALRENDERPROC glEndConditionalRender = nullptr;
+PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer = nullptr;
+PFNGLGETVERTEXATTRIBIIVPROC glGetVertexAttribIiv = nullptr;
+PFNGLGETVERTEXATTRIBIUIVPROC glGetVertexAttribIuiv = nullptr;
+PFNGLVERTEXATTRIBI1IPROC glVertexAttribI1i = nullptr;
+PFNGLVERTEXATTRIBI2IPROC glVertexAttribI2i = nullptr;
+PFNGLVERTEXATTRIBI3IPROC glVertexAttribI3i = nullptr;
+PFNGLVERTEXATTRIBI4IPROC glVertexAttribI4i = nullptr;
+PFNGLVERTEXATTRIBI1UIPROC glVertexAttribI1ui = nullptr;
+PFNGLVERTEXATTRIBI2UIPROC glVertexAttribI2ui = nullptr;
+PFNGLVERTEXATTRIBI3UIPROC glVertexAttribI3ui = nullptr;
+PFNGLVERTEXATTRIBI4UIPROC glVertexAttribI4ui = nullptr;
+PFNGLVERTEXATTRIBI1IVPROC glVertexAttribI1iv = nullptr;
+PFNGLVERTEXATTRIBI2IVPROC glVertexAttribI2iv = nullptr;
+PFNGLVERTEXATTRIBI3IVPROC glVertexAttribI3iv = nullptr;
+PFNGLVERTEXATTRIBI4IVPROC glVertexAttribI4iv = nullptr;
+PFNGLVERTEXATTRIBI1UIVPROC glVertexAttribI1uiv = nullptr;
+PFNGLVERTEXATTRIBI2UIVPROC glVertexAttribI2uiv = nullptr;
+PFNGLVERTEXATTRIBI3UIVPROC glVertexAttribI3uiv = nullptr;
+PFNGLVERTEXATTRIBI4UIVPROC glVertexAttribI4uiv = nullptr;
+PFNGLVERTEXATTRIBI4BVPROC glVertexAttribI4bv = nullptr;
+PFNGLVERTEXATTRIBI4SVPROC glVertexAttribI4sv = nullptr;
+PFNGLVERTEXATTRIBI4UBVPROC glVertexAttribI4ubv = nullptr;
+PFNGLVERTEXATTRIBI4USVPROC glVertexAttribI4usv = nullptr;
+PFNGLGETUNIFORMUIVPROC glGetUniformuiv = nullptr;
+PFNGLBINDFRAGDATALOCATIONPROC glBindFragDataLocation = nullptr;
+PFNGLGETFRAGDATALOCATIONPROC glGetFragDataLocation = nullptr;
+PFNGLUNIFORM1UIPROC glUniform1ui = nullptr;
+PFNGLUNIFORM2UIPROC glUniform2ui = nullptr;
+PFNGLUNIFORM3UIPROC glUniform3ui = nullptr;
+PFNGLUNIFORM4UIPROC glUniform4ui = nullptr;
+PFNGLUNIFORM1UIVPROC glUniform1uiv = nullptr;
+PFNGLUNIFORM2UIVPROC glUniform2uiv = nullptr;
+PFNGLUNIFORM3UIVPROC glUniform3uiv = nullptr;
+PFNGLUNIFORM4UIVPROC glUniform4uiv = nullptr;
+PFNGLTEXPARAMETERIIVPROC glTexParameterIiv = nullptr;
+PFNGLTEXPARAMETERIUIVPROC glTexParameterIuiv = nullptr;
+PFNGLGETTEXPARAMETERIIVPROC glGetTexParameterIiv = nullptr;
+PFNGLGETTEXPARAMETERIUIVPROC glGetTexParameterIuiv = nullptr;
+PFNGLCLEARBUFFERIVPROC glClearBufferiv = nullptr;
+PFNGLCLEARBUFFERUIVPROC glClearBufferuiv = nullptr;
+PFNGLCLEARBUFFERFVPROC glClearBufferfv = nullptr;
+PFNGLCLEARBUFFERFIPROC glClearBufferfi = nullptr;
+PFNGLGETSTRINGIPROC glGetStringi = nullptr;
+PFNGLISRENDERBUFFERPROC glIsRenderbuffer = nullptr;
+PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer = nullptr;
+PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers = nullptr;
+PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers = nullptr;
+PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage = nullptr;
+PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv = nullptr;
+PFNGLISFRAMEBUFFERPROC glIsFramebuffer = nullptr;
+PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = nullptr;
+PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers = nullptr;
+PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers = nullptr;
+PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus = nullptr;
+PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D = nullptr;
+PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D = nullptr;
+PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D = nullptr;
+PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer = nullptr;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv = nullptr;
+PFNGLGENERATEMIPMAPPROC glGenerateMipmap = nullptr;
+PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer = nullptr;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample = nullptr;
+PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer = nullptr;
+PFNGLMAPBUFFERRANGEPROC glMapBufferRange = nullptr;
+PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange = nullptr;
+PFNGLBINDVERTEXARRAYPROC glBindVertexArray = nullptr;
+PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays = nullptr;
+PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = nullptr;
+PFNGLISVERTEXARRAYPROC glIsVertexArray = nullptr;
+
+// GL_VERSION_3_1
+PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced = nullptr;
+PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced = nullptr;
+PFNGLTEXBUFFERPROC glTexBuffer = nullptr;
+PFNGLPRIMITIVERESTARTINDEXPROC glPrimitiveRestartIndex = nullptr;
+PFNGLCOPYBUFFERSUBDATAPROC glCopyBufferSubData = nullptr;
+PFNGLGETUNIFORMINDICESPROC glGetUniformIndices = nullptr;
+PFNGLGETACTIVEUNIFORMSIVPROC glGetActiveUniformsiv = nullptr;
+PFNGLGETACTIVEUNIFORMNAMEPROC glGetActiveUniformName = nullptr;
+PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex = nullptr;
+PFNGLGETACTIVEUNIFORMBLOCKIVPROC glGetActiveUniformBlockiv = nullptr;
+PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glGetActiveUniformBlockName = nullptr;
+PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding = nullptr;
+
+// GL_VERSION_3_2
+PFNGLDRAWELEMENTSBASEVERTEXPROC glDrawElementsBaseVertex = nullptr;
+PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glDrawRangeElementsBaseVertex = nullptr;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glDrawElementsInstancedBaseVertex = nullptr;
+PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glMultiDrawElementsBaseVertex = nullptr;
+PFNGLPROVOKINGVERTEXPROC glProvokingVertex = nullptr;
+PFNGLFENCESYNCPROC glFenceSync = nullptr;
+PFNGLISSYNCPROC glIsSync = nullptr;
+PFNGLDELETESYNCPROC glDeleteSync = nullptr;
+PFNGLCLIENTWAITSYNCPROC glClientWaitSync = nullptr;
+PFNGLWAITSYNCPROC glWaitSync = nullptr;
+PFNGLGETINTEGER64VPROC glGetInteger64v = nullptr;
+PFNGLGETSYNCIVPROC glGetSynciv = nullptr;
+PFNGLGETINTEGER64I_VPROC glGetInteger64i_v = nullptr;
+PFNGLGETBUFFERPARAMETERI64VPROC glGetBufferParameteri64v = nullptr;
+PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture = nullptr;
+PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample = nullptr;
+PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample = nullptr;
+PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv = nullptr;
+PFNGLSAMPLEMASKIPROC glSampleMaski = nullptr;
+
+// GL_VERSION_3_3
+PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glBindFragDataLocationIndexed = nullptr;
+PFNGLGETFRAGDATAINDEXPROC glGetFragDataIndex = nullptr;
+PFNGLGENSAMPLERSPROC glGenSamplers = nullptr;
+PFNGLDELETESAMPLERSPROC glDeleteSamplers = nullptr;
+PFNGLISSAMPLERPROC glIsSampler = nullptr;
+PFNGLBINDSAMPLERPROC glBindSampler = nullptr;
+PFNGLSAMPLERPARAMETERIPROC glSamplerParameteri = nullptr;
+PFNGLSAMPLERPARAMETERIVPROC glSamplerParameteriv = nullptr;
+PFNGLSAMPLERPARAMETERFPROC glSamplerParameterf = nullptr;
+PFNGLSAMPLERPARAMETERFVPROC glSamplerParameterfv = nullptr;
+PFNGLSAMPLERPARAMETERIIVPROC glSamplerParameterIiv = nullptr;
+PFNGLSAMPLERPARAMETERIUIVPROC glSamplerParameterIuiv = nullptr;
+PFNGLGETSAMPLERPARAMETERIVPROC glGetSamplerParameteriv = nullptr;
+PFNGLGETSAMPLERPARAMETERIIVPROC glGetSamplerParameterIiv = nullptr;
+PFNGLGETSAMPLERPARAMETERFVPROC glGetSamplerParameterfv = nullptr;
+PFNGLGETSAMPLERPARAMETERIUIVPROC glGetSamplerParameterIuiv = nullptr;
+PFNGLQUERYCOUNTERPROC glQueryCounter = nullptr;
+PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v = nullptr;
+PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v = nullptr;
+PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor = nullptr;
+PFNGLVERTEXATTRIBP1UIPROC glVertexAttribP1ui = nullptr;
+PFNGLVERTEXATTRIBP1UIVPROC glVertexAttribP1uiv = nullptr;
+PFNGLVERTEXATTRIBP2UIPROC glVertexAttribP2ui = nullptr;
+PFNGLVERTEXATTRIBP2UIVPROC glVertexAttribP2uiv = nullptr;
+PFNGLVERTEXATTRIBP3UIPROC glVertexAttribP3ui = nullptr;
+PFNGLVERTEXATTRIBP3UIVPROC glVertexAttribP3uiv = nullptr;
+PFNGLVERTEXATTRIBP4UIPROC glVertexAttribP4ui = nullptr;
+PFNGLVERTEXATTRIBP4UIVPROC glVertexAttribP4uiv = nullptr;
+PFNGLVERTEXP2UIPROC glVertexP2ui = nullptr;
+PFNGLVERTEXP2UIVPROC glVertexP2uiv = nullptr;
+PFNGLVERTEXP3UIPROC glVertexP3ui = nullptr;
+PFNGLVERTEXP3UIVPROC glVertexP3uiv = nullptr;
+PFNGLVERTEXP4UIPROC glVertexP4ui = nullptr;
+PFNGLVERTEXP4UIVPROC glVertexP4uiv = nullptr;
+PFNGLTEXCOORDP1UIPROC glTexCoordP1ui = nullptr;
+PFNGLTEXCOORDP1UIVPROC glTexCoordP1uiv = nullptr;
+PFNGLTEXCOORDP2UIPROC glTexCoordP2ui = nullptr;
+PFNGLTEXCOORDP2UIVPROC glTexCoordP2uiv = nullptr;
+PFNGLTEXCOORDP3UIPROC glTexCoordP3ui = nullptr;
+PFNGLTEXCOORDP3UIVPROC glTexCoordP3uiv = nullptr;
+PFNGLTEXCOORDP4UIPROC glTexCoordP4ui = nullptr;
+PFNGLTEXCOORDP4UIVPROC glTexCoordP4uiv = nullptr;
+PFNGLMULTITEXCOORDP1UIPROC glMultiTexCoordP1ui = nullptr;
+PFNGLMULTITEXCOORDP1UIVPROC glMultiTexCoordP1uiv = nullptr;
+PFNGLMULTITEXCOORDP2UIPROC glMultiTexCoordP2ui = nullptr;
+PFNGLMULTITEXCOORDP2UIVPROC glMultiTexCoordP2uiv = nullptr;
+PFNGLMULTITEXCOORDP3UIPROC glMultiTexCoordP3ui = nullptr;
+PFNGLMULTITEXCOORDP3UIVPROC glMultiTexCoordP3uiv = nullptr;
+PFNGLMULTITEXCOORDP4UIPROC glMultiTexCoordP4ui = nullptr;
+PFNGLMULTITEXCOORDP4UIVPROC glMultiTexCoordP4uiv = nullptr;
+PFNGLNORMALP3UIPROC glNormalP3ui = nullptr;
+PFNGLNORMALP3UIVPROC glNormalP3uiv = nullptr;
+PFNGLCOLORP3UIPROC glColorP3ui = nullptr;
+PFNGLCOLORP3UIVPROC glColorP3uiv = nullptr;
+PFNGLCOLORP4UIPROC glColorP4ui = nullptr;
+PFNGLCOLORP4UIVPROC glColorP4uiv = nullptr;
+PFNGLSECONDARYCOLORP3UIPROC glSecondaryColorP3ui = nullptr;
+PFNGLSECONDARYCOLORP3UIVPROC glSecondaryColorP3uiv = nullptr;
+
+// GL_VERSION_4_0
+PFNGLMINSAMPLESHADINGPROC glMinSampleShading = nullptr;
+PFNGLBLENDEQUATIONIPROC glBlendEquationi = nullptr;
+PFNGLBLENDEQUATIONSEPARATEIPROC glBlendEquationSeparatei = nullptr;
+PFNGLBLENDFUNCIPROC glBlendFunci = nullptr;
+PFNGLBLENDFUNCSEPARATEIPROC glBlendFuncSeparatei = nullptr;
+PFNGLDRAWARRAYSINDIRECTPROC glDrawArraysIndirect = nullptr;
+PFNGLDRAWELEMENTSINDIRECTPROC glDrawElementsIndirect = nullptr;
+PFNGLUNIFORM1DPROC glUniform1d = nullptr;
+PFNGLUNIFORM2DPROC glUniform2d = nullptr;
+PFNGLUNIFORM3DPROC glUniform3d = nullptr;
+PFNGLUNIFORM4DPROC glUniform4d = nullptr;
+PFNGLUNIFORM1DVPROC glUniform1dv = nullptr;
+PFNGLUNIFORM2DVPROC glUniform2dv = nullptr;
+PFNGLUNIFORM3DVPROC glUniform3dv = nullptr;
+PFNGLUNIFORM4DVPROC glUniform4dv = nullptr;
+PFNGLUNIFORMMATRIX2DVPROC glUniformMatrix2dv = nullptr;
+PFNGLUNIFORMMATRIX3DVPROC glUniformMatrix3dv = nullptr;
+PFNGLUNIFORMMATRIX4DVPROC glUniformMatrix4dv = nullptr;
+PFNGLUNIFORMMATRIX2X3DVPROC glUniformMatrix2x3dv = nullptr;
+PFNGLUNIFORMMATRIX2X4DVPROC glUniformMatrix2x4dv = nullptr;
+PFNGLUNIFORMMATRIX3X2DVPROC glUniformMatrix3x2dv = nullptr;
+PFNGLUNIFORMMATRIX3X4DVPROC glUniformMatrix3x4dv = nullptr;
+PFNGLUNIFORMMATRIX4X2DVPROC glUniformMatrix4x2dv = nullptr;
+PFNGLUNIFORMMATRIX4X3DVPROC glUniformMatrix4x3dv = nullptr;
+PFNGLGETUNIFORMDVPROC glGetUniformdv = nullptr;
+PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC glGetSubroutineUniformLocation = nullptr;
+PFNGLGETSUBROUTINEINDEXPROC glGetSubroutineIndex = nullptr;
+PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC glGetActiveSubroutineUniformiv = nullptr;
+PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC glGetActiveSubroutineUniformName = nullptr;
+PFNGLGETACTIVESUBROUTINENAMEPROC glGetActiveSubroutineName = nullptr;
+PFNGLUNIFORMSUBROUTINESUIVPROC glUniformSubroutinesuiv = nullptr;
+PFNGLGETUNIFORMSUBROUTINEUIVPROC glGetUniformSubroutineuiv = nullptr;
+PFNGLGETPROGRAMSTAGEIVPROC glGetProgramStageiv = nullptr;
+PFNGLPATCHPARAMETERIPROC glPatchParameteri = nullptr;
+PFNGLPATCHPARAMETERFVPROC glPatchParameterfv = nullptr;
+PFNGLBINDTRANSFORMFEEDBACKPROC glBindTransformFeedback = nullptr;
+PFNGLDELETETRANSFORMFEEDBACKSPROC glDeleteTransformFeedbacks = nullptr;
+PFNGLGENTRANSFORMFEEDBACKSPROC glGenTransformFeedbacks = nullptr;
+PFNGLISTRANSFORMFEEDBACKPROC glIsTransformFeedback = nullptr;
+PFNGLPAUSETRANSFORMFEEDBACKPROC glPauseTransformFeedback = nullptr;
+PFNGLRESUMETRANSFORMFEEDBACKPROC glResumeTransformFeedback = nullptr;
+PFNGLDRAWTRANSFORMFEEDBACKPROC glDrawTransformFeedback = nullptr;
+PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC glDrawTransformFeedbackStream = nullptr;
+PFNGLBEGINQUERYINDEXEDPROC glBeginQueryIndexed = nullptr;
+PFNGLENDQUERYINDEXEDPROC glEndQueryIndexed = nullptr;
+PFNGLGETQUERYINDEXEDIVPROC glGetQueryIndexediv = nullptr;
+
+// GL_VERSION_4_1
+PFNGLRELEASESHADERCOMPILERPROC glReleaseShaderCompiler = nullptr;
+PFNGLSHADERBINARYPROC glShaderBinary = nullptr;
+PFNGLGETSHADERPRECISIONFORMATPROC glGetShaderPrecisionFormat = nullptr;
+PFNGLDEPTHRANGEFPROC glDepthRangef = nullptr;
+PFNGLCLEARDEPTHFPROC glClearDepthf = nullptr;
+PFNGLGETPROGRAMBINARYPROC glGetProgramBinary = nullptr;
+PFNGLPROGRAMBINARYPROC glProgramBinary = nullptr;
+PFNGLPROGRAMPARAMETERIPROC glProgramParameteri = nullptr;
+PFNGLUSEPROGRAMSTAGESPROC glUseProgramStages = nullptr;
+PFNGLACTIVESHADERPROGRAMPROC glActiveShaderProgram = nullptr;
+PFNGLCREATESHADERPROGRAMVPROC glCreateShaderProgramv = nullptr;
+PFNGLBINDPROGRAMPIPELINEPROC glBindProgramPipeline = nullptr;
+PFNGLDELETEPROGRAMPIPELINESPROC glDeleteProgramPipelines = nullptr;
+PFNGLGENPROGRAMPIPELINESPROC glGenProgramPipelines = nullptr;
+PFNGLISPROGRAMPIPELINEPROC glIsProgramPipeline = nullptr;
+PFNGLGETPROGRAMPIPELINEIVPROC glGetProgramPipelineiv = nullptr;
+PFNGLPROGRAMUNIFORM1IPROC glProgramUniform1i = nullptr;
+PFNGLPROGRAMUNIFORM1IVPROC glProgramUniform1iv = nullptr;
+PFNGLPROGRAMUNIFORM1FPROC glProgramUniform1f = nullptr;
+PFNGLPROGRAMUNIFORM1FVPROC glProgramUniform1fv = nullptr;
+PFNGLPROGRAMUNIFORM1DPROC glProgramUniform1d = nullptr;
+PFNGLPROGRAMUNIFORM1DVPROC glProgramUniform1dv = nullptr;
+PFNGLPROGRAMUNIFORM1UIPROC glProgramUniform1ui = nullptr;
+PFNGLPROGRAMUNIFORM1UIVPROC glProgramUniform1uiv = nullptr;
+PFNGLPROGRAMUNIFORM2IPROC glProgramUniform2i = nullptr;
+PFNGLPROGRAMUNIFORM2IVPROC glProgramUniform2iv = nullptr;
+PFNGLPROGRAMUNIFORM2FPROC glProgramUniform2f = nullptr;
+PFNGLPROGRAMUNIFORM2FVPROC glProgramUniform2fv = nullptr;
+PFNGLPROGRAMUNIFORM2DPROC glProgramUniform2d = nullptr;
+PFNGLPROGRAMUNIFORM2DVPROC glProgramUniform2dv = nullptr;
+PFNGLPROGRAMUNIFORM2UIPROC glProgramUniform2ui = nullptr;
+PFNGLPROGRAMUNIFORM2UIVPROC glProgramUniform2uiv = nullptr;
+PFNGLPROGRAMUNIFORM3IPROC glProgramUniform3i = nullptr;
+PFNGLPROGRAMUNIFORM3IVPROC glProgramUniform3iv = nullptr;
+PFNGLPROGRAMUNIFORM3FPROC glProgramUniform3f = nullptr;
+PFNGLPROGRAMUNIFORM3FVPROC glProgramUniform3fv = nullptr;
+PFNGLPROGRAMUNIFORM3DPROC glProgramUniform3d = nullptr;
+PFNGLPROGRAMUNIFORM3DVPROC glProgramUniform3dv = nullptr;
+PFNGLPROGRAMUNIFORM3UIPROC glProgramUniform3ui = nullptr;
+PFNGLPROGRAMUNIFORM3UIVPROC glProgramUniform3uiv = nullptr;
+PFNGLPROGRAMUNIFORM4IPROC glProgramUniform4i = nullptr;
+PFNGLPROGRAMUNIFORM4IVPROC glProgramUniform4iv = nullptr;
+PFNGLPROGRAMUNIFORM4FPROC glProgramUniform4f = nullptr;
+PFNGLPROGRAMUNIFORM4FVPROC glProgramUniform4fv = nullptr;
+PFNGLPROGRAMUNIFORM4DPROC glProgramUniform4d = nullptr;
+PFNGLPROGRAMUNIFORM4DVPROC glProgramUniform4dv = nullptr;
+PFNGLPROGRAMUNIFORM4UIPROC glProgramUniform4ui = nullptr;
+PFNGLPROGRAMUNIFORM4UIVPROC glProgramUniform4uiv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX2FVPROC glProgramUniformMatrix2fv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX3FVPROC glProgramUniformMatrix3fv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX4FVPROC glProgramUniformMatrix4fv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX2DVPROC glProgramUniformMatrix2dv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX3DVPROC glProgramUniformMatrix3dv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX4DVPROC glProgramUniformMatrix4dv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC glProgramUniformMatrix2x3fv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC glProgramUniformMatrix3x2fv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC glProgramUniformMatrix2x4fv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC glProgramUniformMatrix4x2fv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC glProgramUniformMatrix3x4fv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC glProgramUniformMatrix4x3fv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC glProgramUniformMatrix2x3dv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC glProgramUniformMatrix3x2dv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC glProgramUniformMatrix2x4dv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC glProgramUniformMatrix4x2dv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC glProgramUniformMatrix3x4dv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC glProgramUniformMatrix4x3dv = nullptr;
+PFNGLVALIDATEPROGRAMPIPELINEPROC glValidateProgramPipeline = nullptr;
+PFNGLGETPROGRAMPIPELINEINFOLOGPROC glGetProgramPipelineInfoLog = nullptr;
+PFNGLVERTEXATTRIBL1DPROC glVertexAttribL1d = nullptr;
+PFNGLVERTEXATTRIBL2DPROC glVertexAttribL2d = nullptr;
+PFNGLVERTEXATTRIBL3DPROC glVertexAttribL3d = nullptr;
+PFNGLVERTEXATTRIBL4DPROC glVertexAttribL4d = nullptr;
+PFNGLVERTEXATTRIBL1DVPROC glVertexAttribL1dv = nullptr;
+PFNGLVERTEXATTRIBL2DVPROC glVertexAttribL2dv = nullptr;
+PFNGLVERTEXATTRIBL3DVPROC glVertexAttribL3dv = nullptr;
+PFNGLVERTEXATTRIBL4DVPROC glVertexAttribL4dv = nullptr;
+PFNGLVERTEXATTRIBLPOINTERPROC glVertexAttribLPointer = nullptr;
+PFNGLGETVERTEXATTRIBLDVPROC glGetVertexAttribLdv = nullptr;
+PFNGLVIEWPORTARRAYVPROC glViewportArrayv = nullptr;
+PFNGLVIEWPORTINDEXEDFPROC glViewportIndexedf = nullptr;
+PFNGLVIEWPORTINDEXEDFVPROC glViewportIndexedfv = nullptr;
+PFNGLSCISSORARRAYVPROC glScissorArrayv = nullptr;
+PFNGLSCISSORINDEXEDPROC glScissorIndexed = nullptr;
+PFNGLSCISSORINDEXEDVPROC glScissorIndexedv = nullptr;
+PFNGLDEPTHRANGEARRAYVPROC glDepthRangeArrayv = nullptr;
+PFNGLDEPTHRANGEINDEXEDPROC glDepthRangeIndexed = nullptr;
+PFNGLGETFLOATI_VPROC glGetFloati_v = nullptr;
+PFNGLGETDOUBLEI_VPROC glGetDoublei_v = nullptr;
+
+// GL_VERSION_4_2
+PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC glDrawArraysInstancedBaseInstance = nullptr;
+PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC glDrawElementsInstancedBaseInstance = nullptr;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC glDrawElementsInstancedBaseVertexBaseInstance = nullptr;
+PFNGLGETINTERNALFORMATIVPROC glGetInternalformativ = nullptr;
+PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC glGetActiveAtomicCounterBufferiv = nullptr;
+PFNGLBINDIMAGETEXTUREPROC glBindImageTexture = nullptr;
+PFNGLMEMORYBARRIERPROC glMemoryBarrier = nullptr;
+PFNGLTEXSTORAGE1DPROC glTexStorage1D = nullptr;
+PFNGLTEXSTORAGE2DPROC glTexStorage2D = nullptr;
+PFNGLTEXSTORAGE3DPROC glTexStorage3D = nullptr;
+PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC glDrawTransformFeedbackInstanced = nullptr;
+PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC glDrawTransformFeedbackStreamInstanced = nullptr;
+
+// GL_VERSION_4_3
+PFNGLCLEARBUFFERDATAPROC glClearBufferData = nullptr;
+PFNGLCLEARBUFFERSUBDATAPROC glClearBufferSubData = nullptr;
+PFNGLDISPATCHCOMPUTEPROC glDispatchCompute = nullptr;
+PFNGLDISPATCHCOMPUTEINDIRECTPROC glDispatchComputeIndirect = nullptr;
+PFNGLCOPYIMAGESUBDATAPROC glCopyImageSubData = nullptr;
+PFNGLFRAMEBUFFERPARAMETERIPROC glFramebufferParameteri = nullptr;
+PFNGLGETFRAMEBUFFERPARAMETERIVPROC glGetFramebufferParameteriv = nullptr;
+PFNGLGETINTERNALFORMATI64VPROC glGetInternalformati64v = nullptr;
+PFNGLINVALIDATETEXSUBIMAGEPROC glInvalidateTexSubImage = nullptr;
+PFNGLINVALIDATETEXIMAGEPROC glInvalidateTexImage = nullptr;
+PFNGLINVALIDATEBUFFERSUBDATAPROC glInvalidateBufferSubData = nullptr;
+PFNGLINVALIDATEBUFFERDATAPROC glInvalidateBufferData = nullptr;
+PFNGLINVALIDATEFRAMEBUFFERPROC glInvalidateFramebuffer = nullptr;
+PFNGLINVALIDATESUBFRAMEBUFFERPROC glInvalidateSubFramebuffer = nullptr;
+PFNGLMULTIDRAWARRAYSINDIRECTPROC glMultiDrawArraysIndirect = nullptr;
+PFNGLMULTIDRAWELEMENTSINDIRECTPROC glMultiDrawElementsIndirect = nullptr;
+PFNGLGETPROGRAMINTERFACEIVPROC glGetProgramInterfaceiv = nullptr;
+PFNGLGETPROGRAMRESOURCEINDEXPROC glGetProgramResourceIndex = nullptr;
+PFNGLGETPROGRAMRESOURCENAMEPROC glGetProgramResourceName = nullptr;
+PFNGLGETPROGRAMRESOURCEIVPROC glGetProgramResourceiv = nullptr;
+PFNGLGETPROGRAMRESOURCELOCATIONPROC glGetProgramResourceLocation = nullptr;
+PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC glGetProgramResourceLocationIndex = nullptr;
+PFNGLSHADERSTORAGEBLOCKBINDINGPROC glShaderStorageBlockBinding = nullptr;
+PFNGLTEXBUFFERRANGEPROC glTexBufferRange = nullptr;
+PFNGLTEXSTORAGE2DMULTISAMPLEPROC glTexStorage2DMultisample = nullptr;
+PFNGLTEXSTORAGE3DMULTISAMPLEPROC glTexStorage3DMultisample = nullptr;
+PFNGLTEXTUREVIEWPROC glTextureView = nullptr;
+PFNGLBINDVERTEXBUFFERPROC glBindVertexBuffer = nullptr;
+PFNGLVERTEXATTRIBFORMATPROC glVertexAttribFormat = nullptr;
+PFNGLVERTEXATTRIBIFORMATPROC glVertexAttribIFormat = nullptr;
+PFNGLVERTEXATTRIBLFORMATPROC glVertexAttribLFormat = nullptr;
+PFNGLVERTEXATTRIBBINDINGPROC glVertexAttribBinding = nullptr;
+PFNGLVERTEXBINDINGDIVISORPROC glVertexBindingDivisor = nullptr;
+PFNGLDEBUGMESSAGECONTROLPROC glDebugMessageControl = nullptr;
+PFNGLDEBUGMESSAGEINSERTPROC glDebugMessageInsert = nullptr;
+PFNGLDEBUGMESSAGECALLBACKPROC glDebugMessageCallback = nullptr;
+PFNGLGETDEBUGMESSAGELOGPROC glGetDebugMessageLog = nullptr;
+PFNGLPUSHDEBUGGROUPPROC glPushDebugGroup = nullptr;
+PFNGLPOPDEBUGGROUPPROC glPopDebugGroup = nullptr;
+PFNGLOBJECTLABELPROC glObjectLabel = nullptr;
+PFNGLGETOBJECTLABELPROC glGetObjectLabel = nullptr;
+PFNGLOBJECTPTRLABELPROC glObjectPtrLabel = nullptr;
+PFNGLGETOBJECTPTRLABELPROC glGetObjectPtrLabel = nullptr;
+
+// GL_VERSION_4_4
+PFNGLBUFFERSTORAGEPROC glBufferStorage = nullptr;
+PFNGLCLEARTEXIMAGEPROC glClearTexImage = nullptr;
+PFNGLCLEARTEXSUBIMAGEPROC glClearTexSubImage = nullptr;
+PFNGLBINDBUFFERSBASEPROC glBindBuffersBase = nullptr;
+PFNGLBINDBUFFERSRANGEPROC glBindBuffersRange = nullptr;
+PFNGLBINDTEXTURESPROC glBindTextures = nullptr;
+PFNGLBINDSAMPLERSPROC glBindSamplers = nullptr;
+PFNGLBINDIMAGETEXTURESPROC glBindImageTextures = nullptr;
+PFNGLBINDVERTEXBUFFERSPROC glBindVertexBuffers = nullptr;
+
+// GL_VERSION_4_5
+PFNGLCLIPCONTROLPROC glClipControl = nullptr;
+PFNGLCREATETRANSFORMFEEDBACKSPROC glCreateTransformFeedbacks = nullptr;
+PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC glTransformFeedbackBufferBase = nullptr;
+PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC glTransformFeedbackBufferRange = nullptr;
+PFNGLGETTRANSFORMFEEDBACKIVPROC glGetTransformFeedbackiv = nullptr;
+PFNGLGETTRANSFORMFEEDBACKI_VPROC glGetTransformFeedbacki_v = nullptr;
+PFNGLGETTRANSFORMFEEDBACKI64_VPROC glGetTransformFeedbacki64_v = nullptr;
+PFNGLCREATEBUFFERSPROC glCreateBuffers = nullptr;
+PFNGLNAMEDBUFFERSTORAGEPROC glNamedBufferStorage = nullptr;
+PFNGLNAMEDBUFFERDATAPROC glNamedBufferData = nullptr;
+PFNGLNAMEDBUFFERSUBDATAPROC glNamedBufferSubData = nullptr;
+PFNGLCOPYNAMEDBUFFERSUBDATAPROC glCopyNamedBufferSubData = nullptr;
+PFNGLCLEARNAMEDBUFFERDATAPROC glClearNamedBufferData = nullptr;
+PFNGLCLEARNAMEDBUFFERSUBDATAPROC glClearNamedBufferSubData = nullptr;
+PFNGLMAPNAMEDBUFFERPROC glMapNamedBuffer = nullptr;
+PFNGLMAPNAMEDBUFFERRANGEPROC glMapNamedBufferRange = nullptr;
+PFNGLUNMAPNAMEDBUFFERPROC glUnmapNamedBuffer = nullptr;
+PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC glFlushMappedNamedBufferRange = nullptr;
+PFNGLGETNAMEDBUFFERPARAMETERIVPROC glGetNamedBufferParameteriv = nullptr;
+PFNGLGETNAMEDBUFFERPARAMETERI64VPROC glGetNamedBufferParameteri64v = nullptr;
+PFNGLGETNAMEDBUFFERPOINTERVPROC glGetNamedBufferPointerv = nullptr;
+PFNGLGETNAMEDBUFFERSUBDATAPROC glGetNamedBufferSubData = nullptr;
+PFNGLCREATEFRAMEBUFFERSPROC glCreateFramebuffers = nullptr;
+PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC glNamedFramebufferRenderbuffer = nullptr;
+PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC glNamedFramebufferParameteri = nullptr;
+PFNGLNAMEDFRAMEBUFFERTEXTUREPROC glNamedFramebufferTexture = nullptr;
+PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC glNamedFramebufferTextureLayer = nullptr;
+PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC glNamedFramebufferDrawBuffer = nullptr;
+PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC glNamedFramebufferDrawBuffers = nullptr;
+PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC glNamedFramebufferReadBuffer = nullptr;
+PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC glInvalidateNamedFramebufferData = nullptr;
+PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC glInvalidateNamedFramebufferSubData = nullptr;
+PFNGLCLEARNAMEDFRAMEBUFFERIVPROC glClearNamedFramebufferiv = nullptr;
+PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC glClearNamedFramebufferuiv = nullptr;
+PFNGLCLEARNAMEDFRAMEBUFFERFVPROC glClearNamedFramebufferfv = nullptr;
+PFNGLCLEARNAMEDFRAMEBUFFERFIPROC glClearNamedFramebufferfi = nullptr;
+PFNGLBLITNAMEDFRAMEBUFFERPROC glBlitNamedFramebuffer = nullptr;
+PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC glCheckNamedFramebufferStatus = nullptr;
+PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC glGetNamedFramebufferParameteriv = nullptr;
+PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetNamedFramebufferAttachmentParameteriv = nullptr;
+PFNGLCREATERENDERBUFFERSPROC glCreateRenderbuffers = nullptr;
+PFNGLNAMEDRENDERBUFFERSTORAGEPROC glNamedRenderbufferStorage = nullptr;
+PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC glNamedRenderbufferStorageMultisample = nullptr;
+PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC glGetNamedRenderbufferParameteriv = nullptr;
+PFNGLCREATETEXTURESPROC glCreateTextures = nullptr;
+PFNGLTEXTUREBUFFERPROC glTextureBuffer = nullptr;
+PFNGLTEXTUREBUFFERRANGEPROC glTextureBufferRange = nullptr;
+PFNGLTEXTURESTORAGE1DPROC glTextureStorage1D = nullptr;
+PFNGLTEXTURESTORAGE2DPROC glTextureStorage2D = nullptr;
+PFNGLTEXTURESTORAGE3DPROC glTextureStorage3D = nullptr;
+PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC glTextureStorage2DMultisample = nullptr;
+PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC glTextureStorage3DMultisample = nullptr;
+PFNGLTEXTURESUBIMAGE1DPROC glTextureSubImage1D = nullptr;
+PFNGLTEXTURESUBIMAGE2DPROC glTextureSubImage2D = nullptr;
+PFNGLTEXTURESUBIMAGE3DPROC glTextureSubImage3D = nullptr;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC glCompressedTextureSubImage1D = nullptr;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC glCompressedTextureSubImage2D = nullptr;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC glCompressedTextureSubImage3D = nullptr;
+PFNGLCOPYTEXTURESUBIMAGE1DPROC glCopyTextureSubImage1D = nullptr;
+PFNGLCOPYTEXTURESUBIMAGE2DPROC glCopyTextureSubImage2D = nullptr;
+PFNGLCOPYTEXTURESUBIMAGE3DPROC glCopyTextureSubImage3D = nullptr;
+PFNGLTEXTUREPARAMETERFPROC glTextureParameterf = nullptr;
+PFNGLTEXTUREPARAMETERFVPROC glTextureParameterfv = nullptr;
+PFNGLTEXTUREPARAMETERIPROC glTextureParameteri = nullptr;
+PFNGLTEXTUREPARAMETERIIVPROC glTextureParameterIiv = nullptr;
+PFNGLTEXTUREPARAMETERIUIVPROC glTextureParameterIuiv = nullptr;
+PFNGLTEXTUREPARAMETERIVPROC glTextureParameteriv = nullptr;
+PFNGLGENERATETEXTUREMIPMAPPROC glGenerateTextureMipmap = nullptr;
+PFNGLBINDTEXTUREUNITPROC glBindTextureUnit = nullptr;
+PFNGLGETTEXTUREIMAGEPROC glGetTextureImage = nullptr;
+PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC glGetCompressedTextureImage = nullptr;
+PFNGLGETTEXTURELEVELPARAMETERFVPROC glGetTextureLevelParameterfv = nullptr;
+PFNGLGETTEXTURELEVELPARAMETERIVPROC glGetTextureLevelParameteriv = nullptr;
+PFNGLGETTEXTUREPARAMETERFVPROC glGetTextureParameterfv = nullptr;
+PFNGLGETTEXTUREPARAMETERIIVPROC glGetTextureParameterIiv = nullptr;
+PFNGLGETTEXTUREPARAMETERIUIVPROC glGetTextureParameterIuiv = nullptr;
+PFNGLGETTEXTUREPARAMETERIVPROC glGetTextureParameteriv = nullptr;
+PFNGLCREATEVERTEXARRAYSPROC glCreateVertexArrays = nullptr;
+PFNGLDISABLEVERTEXARRAYATTRIBPROC glDisableVertexArrayAttrib = nullptr;
+PFNGLENABLEVERTEXARRAYATTRIBPROC glEnableVertexArrayAttrib = nullptr;
+PFNGLVERTEXARRAYELEMENTBUFFERPROC glVertexArrayElementBuffer = nullptr;
+PFNGLVERTEXARRAYVERTEXBUFFERPROC glVertexArrayVertexBuffer = nullptr;
+PFNGLVERTEXARRAYVERTEXBUFFERSPROC glVertexArrayVertexBuffers = nullptr;
+PFNGLVERTEXARRAYATTRIBBINDINGPROC glVertexArrayAttribBinding = nullptr;
+PFNGLVERTEXARRAYATTRIBFORMATPROC glVertexArrayAttribFormat = nullptr;
+PFNGLVERTEXARRAYATTRIBIFORMATPROC glVertexArrayAttribIFormat = nullptr;
+PFNGLVERTEXARRAYATTRIBLFORMATPROC glVertexArrayAttribLFormat = nullptr;
+PFNGLVERTEXARRAYBINDINGDIVISORPROC glVertexArrayBindingDivisor = nullptr;
+PFNGLGETVERTEXARRAYIVPROC glGetVertexArrayiv = nullptr;
+PFNGLGETVERTEXARRAYINDEXEDIVPROC glGetVertexArrayIndexediv = nullptr;
+PFNGLGETVERTEXARRAYINDEXED64IVPROC glGetVertexArrayIndexed64iv = nullptr;
+PFNGLCREATESAMPLERSPROC glCreateSamplers = nullptr;
+PFNGLCREATEPROGRAMPIPELINESPROC glCreateProgramPipelines = nullptr;
+PFNGLCREATEQUERIESPROC glCreateQueries = nullptr;
+PFNGLGETQUERYBUFFEROBJECTI64VPROC glGetQueryBufferObjecti64v = nullptr;
+PFNGLGETQUERYBUFFEROBJECTIVPROC glGetQueryBufferObjectiv = nullptr;
+PFNGLGETQUERYBUFFEROBJECTUI64VPROC glGetQueryBufferObjectui64v = nullptr;
+PFNGLGETQUERYBUFFEROBJECTUIVPROC glGetQueryBufferObjectuiv = nullptr;
+PFNGLMEMORYBARRIERBYREGIONPROC glMemoryBarrierByRegion = nullptr;
+PFNGLGETTEXTURESUBIMAGEPROC glGetTextureSubImage = nullptr;
+PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC glGetCompressedTextureSubImage = nullptr;
+PFNGLGETGRAPHICSRESETSTATUSPROC glGetGraphicsResetStatus = nullptr;
+PFNGLGETNCOMPRESSEDTEXIMAGEPROC glGetnCompressedTexImage = nullptr;
+PFNGLGETNTEXIMAGEPROC glGetnTexImage = nullptr;
+PFNGLGETNUNIFORMDVPROC glGetnUniformdv = nullptr;
+PFNGLGETNUNIFORMFVPROC glGetnUniformfv = nullptr;
+PFNGLGETNUNIFORMIVPROC glGetnUniformiv = nullptr;
+PFNGLGETNUNIFORMUIVPROC glGetnUniformuiv = nullptr;
+PFNGLREADNPIXELSPROC glReadnPixels = nullptr;
+PFNGLGETNMAPDVPROC glGetnMapdv = nullptr;
+PFNGLGETNMAPFVPROC glGetnMapfv = nullptr;
+PFNGLGETNMAPIVPROC glGetnMapiv = nullptr;
+PFNGLGETNPIXELMAPFVPROC glGetnPixelMapfv = nullptr;
+PFNGLGETNPIXELMAPUIVPROC glGetnPixelMapuiv = nullptr;
+PFNGLGETNPIXELMAPUSVPROC glGetnPixelMapusv = nullptr;
+PFNGLGETNPOLYGONSTIPPLEPROC glGetnPolygonStipple = nullptr;
+PFNGLGETNCOLORTABLEPROC glGetnColorTable = nullptr;
+PFNGLGETNCONVOLUTIONFILTERPROC glGetnConvolutionFilter = nullptr;
+PFNGLGETNSEPARABLEFILTERPROC glGetnSeparableFilter = nullptr;
+PFNGLGETNHISTOGRAMPROC glGetnHistogram = nullptr;
+PFNGLGETNMINMAXPROC glGetnMinmax = nullptr;
+PFNGLTEXTUREBARRIERPROC glTextureBarrier = nullptr;
+
+// GL_VERSION_4_6
+PFNGLSPECIALIZESHADERPROC glSpecializeShader = nullptr;
+PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC glMultiDrawArraysIndirectCount = nullptr;
+PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC glMultiDrawElementsIndirectCount = nullptr;
+PFNGLPOLYGONOFFSETCLAMPPROC glPolygonOffsetClamp = nullptr;
-#if LL_LINUX_NV_GL_HEADERS
-// linux nvidia headers. these define these differently to mesa's. ugh.
-PFNGLACTIVETEXTUREARBPROC glActiveTextureARB = NULL;
-PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB = NULL;
-PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements = NULL;
-#endif // LL_LINUX_NV_GL_HEADERS
#endif
LLGLManager gGLManager;
@@ -406,42 +973,12 @@ LLGLManager gGLManager;
LLGLManager::LLGLManager() :
mInited(FALSE),
mIsDisabled(FALSE),
-
- mHasMultitexture(FALSE),
- mHasATIMemInfo(FALSE),
- mHasAMDAssociations(FALSE),
- mHasNVXMemInfo(FALSE),
- mNumTextureUnits(1),
- mHasMipMapGeneration(FALSE),
- mHasCompressedTextures(FALSE),
- mHasFramebufferObject(FALSE),
mMaxSamples(0),
- mHasBlendFuncSeparate(FALSE),
- mHasSync(FALSE),
- mHasVertexBufferObject(FALSE),
- mHasVertexArrayObject(FALSE),
- mHasMapBufferRange(FALSE),
- mHasFlushBufferRange(FALSE),
- mHasPBuffer(FALSE),
- mNumTextureImageUnits(0),
- mHasOcclusionQuery(FALSE),
- mHasTimerQuery(FALSE),
- mHasOcclusionQuery2(FALSE),
- mHasPointParameters(FALSE),
- mHasDrawBuffers(FALSE),
- mHasTextureRectangle(FALSE),
- mHasTextureMultisample(FALSE),
- mHasTransformFeedback(FALSE),
+ mNumTextureImageUnits(1),
mMaxSampleMaskWords(0),
mMaxColorTextureSamples(0),
mMaxDepthTextureSamples(0),
mMaxIntegerSamples(0),
-
- mHasAnisotropic(FALSE),
- mHasARBEnvCombine(FALSE),
- mHasCubeMap(FALSE),
- mHasDebugOutput(FALSE),
-
mIsAMD(FALSE),
mIsNVIDIA(FALSE),
mIsIntel(FALSE),
@@ -449,9 +986,6 @@ LLGLManager::LLGLManager() :
mIsMobileGF(FALSE),
#endif
mHasRequirements(TRUE),
-
- mHasSeparateSpecularColor(FALSE),
-
mDriverVersionMajor(1),
mDriverVersionMinor(0),
mDriverVersionRelease(0),
@@ -469,7 +1003,6 @@ LLGLManager::LLGLManager() :
//---------------------------------------------------------------------
void LLGLManager::initWGL()
{
- mHasPBuffer = FALSE;
#if LL_WINDOWS && !LL_MESA_HEADLESS
if (!glh_init_extensions("WGL_ARB_pixel_format"))
{
@@ -508,10 +1041,6 @@ void LLGLManager::initWGL()
{
LL_WARNS("RenderInit") << "No ARB WGL render texture extensions" << LL_ENDL;
}
-
- mHasPBuffer = ExtensionExists("WGL_ARB_pbuffer", gGLHExts.mSysExts) &&
- ExtensionExists("WGL_ARB_render_texture", gGLHExts.mSysExts) &&
- ExtensionExists("WGL_ARB_pixel_format", gGLHExts.mSysExts);
#endif
}
@@ -523,9 +1052,7 @@ bool LLGLManager::initGL()
LL_ERRS("RenderInit") << "Calling init on LLGLManager after already initialized!" << LL_ENDL;
}
- stop_glerror();
-
-#if LL_WINDOWS
+#if 0 && LL_WINDOWS
if (!glGetStringi)
{
glGetStringi = (PFNGLGETSTRINGIPROC) GLH_EXT_GET_PROC_ADDRESS("glGetStringi");
@@ -560,8 +1087,6 @@ bool LLGLManager::initGL()
}
#endif
- stop_glerror();
-
// Extract video card strings and convert to upper case to
// work around driver-to-driver variation in capitalization.
mGLVendor = ll_safe_string((const char *)glGetString(GL_VENDOR));
@@ -582,12 +1107,14 @@ bool LLGLManager::initGL()
{
parse_glsl_version(mGLSLVersionMajor, mGLSLVersionMinor);
-#if LL_DARWIN
+#if 0 && LL_DARWIN
+ // TODO maybe switch to using a core profile for GL 3.2?
+ // https://stackoverflow.com/a/19868861
//never use GLSL greater than 1.20 on OSX
- if (mGLSLVersionMajor > 1 || mGLSLVersionMinor >= 30)
+ if (mGLSLVersionMajor > 1 || mGLSLVersionMinor > 30)
{
mGLSLVersionMajor = 1;
- mGLSLVersionMinor = 20;
+ mGLSLVersionMinor = 30;
}
#endif
}
@@ -631,10 +1158,8 @@ bool LLGLManager::initGL()
mGLVendorShort = "MISC";
}
- stop_glerror();
// This is called here because it depends on the setting of mIsGF2or4MX, and sets up mHasMultitexture.
initExtensions();
- stop_glerror();
S32 old_vram = mVRAM;
mVRAM = 0;
@@ -670,23 +1195,6 @@ bool LLGLManager::initGL()
}
#endif
- if (mHasATIMemInfo && mVRAM == 0)
- { //ask the gl how much vram is free at startup and attempt to use no more than half of that
- S32 meminfo[4];
- glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo);
-
- mVRAM = meminfo[0] / 1024;
- LL_WARNS("RenderInit") << "VRAM Detected (ATIMemInfo):" << mVRAM << LL_ENDL;
- }
-
- if (mHasNVXMemInfo && mVRAM == 0)
- {
- S32 dedicated_memory;
- glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &dedicated_memory);
- mVRAM = dedicated_memory/1024;
- LL_WARNS("RenderInit") << "VRAM Detected (NVXMemInfo):" << mVRAM << LL_ENDL;
- }
-
#if LL_WINDOWS
if (mVRAM < 256)
{
@@ -712,72 +1220,20 @@ bool LLGLManager::initGL()
mVRAM = old_vram;
}
- stop_glerror();
-
- GLint num_tex_image_units;
- glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &num_tex_image_units);
- mNumTextureImageUnits = llmin(num_tex_image_units, 32);
-
- if (mHasMultitexture)
- {
- if (LLRender::sGLCoreProfile)
- {
- mNumTextureUnits = llmin(mNumTextureImageUnits, MAX_GL_TEXTURE_UNITS);
- }
- else
- {
- GLint num_tex_units;
- glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &num_tex_units);
- mNumTextureUnits = llmin(num_tex_units, (GLint)MAX_GL_TEXTURE_UNITS);
- if (mIsIntel)
- {
- mNumTextureUnits = llmin(mNumTextureUnits, 2);
- }
- }
- }
- else
- {
- mHasRequirements = FALSE;
-
- // We don't support cards that don't support the GL_ARB_multitexture extension
- LL_WARNS("RenderInit") << "GL Drivers do not support GL_ARB_multitexture" << LL_ENDL;
- return false;
- }
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mNumTextureImageUnits);
+ 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);
+ glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
- if (!mHasFramebufferObject)
+ if (mGLVersion >= 4.59f)
{
- mHasRequirements = FALSE;
-
- LL_WARNS("RenderInit") << "GL Drivers do not support GL_ARB_framebuffer_object" << LL_ENDL;
- return false;
+ glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &mMaxAnisotropy);
}
-
- stop_glerror();
-
- if (mHasTextureMultisample)
- {
- 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);
- }
-
- stop_glerror();
-
- //HACK always disable texture multisample, use FXAA instead
- mHasTextureMultisample = FALSE;
-
- if (mHasFramebufferObject)
- {
- glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
- }
- stop_glerror();
-
initGLStates();
- stop_glerror();
-
return true;
}
@@ -879,62 +1335,22 @@ void LLGLManager::asLLSD(LLSD& info)
info["vram"] = mVRAM;
- // Extensions used by everyone
- info["has_multitexture"] = mHasMultitexture;
- info["has_ati_mem_info"] = mHasATIMemInfo;
- info["has_nvx_mem_info"] = mHasNVXMemInfo;
- info["num_texture_units"] = mNumTextureUnits;
- info["has_mip_map_generation"] = mHasMipMapGeneration;
- info["has_compressed_textures"] = mHasCompressedTextures;
- info["has_framebuffer_object"] = mHasFramebufferObject;
+ // OpenGL limits
info["max_samples"] = mMaxSamples;
- info["has_blend_func_separate"] = mHasBlendFuncSeparate;
-
- // ARB Extensions
- info["has_vertex_buffer_object"] = mHasVertexBufferObject;
- info["has_vertex_array_object"] = mHasVertexArrayObject;
- info["has_sync"] = mHasSync;
- info["has_map_buffer_range"] = mHasMapBufferRange;
- info["has_flush_buffer_range"] = mHasFlushBufferRange;
- info["has_pbuffer"] = mHasPBuffer;
- info["has_shader_objects"] = std::string("Assumed TRUE"); // was mHasShaderObjects;
- info["has_vertex_shader"] = std::string("Assumed TRUE"); // was mHasVertexShader;
- info["has_fragment_shader"] = std::string("Assumed TRUE"); // was mHasFragmentShader;
info["num_texture_image_units"] = mNumTextureImageUnits;
- info["has_occlusion_query"] = mHasOcclusionQuery;
- info["has_timer_query"] = mHasTimerQuery;
- info["has_occlusion_query2"] = mHasOcclusionQuery2;
- info["has_point_parameters"] = mHasPointParameters;
- info["has_draw_buffers"] = mHasDrawBuffers;
- info["has_depth_clamp"] = mHasDepthClamp;
- info["has_texture_rectangle"] = mHasTextureRectangle;
- info["has_texture_multisample"] = mHasTextureMultisample;
- info["has_transform_feedback"] = mHasTransformFeedback;
info["max_sample_mask_words"] = mMaxSampleMaskWords;
info["max_color_texture_samples"] = mMaxColorTextureSamples;
info["max_depth_texture_samples"] = mMaxDepthTextureSamples;
info["max_integer_samples"] = mMaxIntegerSamples;
+ info["max_vertex_range"] = mGLMaxVertexRange;
+ info["max_index_range"] = mGLMaxIndexRange;
+ info["max_texture_size"] = mGLMaxTextureSize;
- // Other extensions.
- info["has_anisotropic"] = mHasAnisotropic;
- info["has_arb_env_combine"] = mHasARBEnvCombine;
- info["has_cube_map"] = mHasCubeMap;
- info["has_debug_output"] = mHasDebugOutput;
- info["has_srgb_texture"] = mHassRGBTexture;
- info["has_srgb_framebuffer"] = mHassRGBFramebuffer;
- info["has_texture_srgb_decode"] = mHasTexturesRGBDecode;
-
- // Vendor-specific extensions
+ // Which vendor
info["is_ati"] = mIsAMD; // note, do not rename is_ati to is_amd without coordinating with DW
info["is_nvidia"] = mIsNVIDIA;
info["is_intel"] = mIsIntel;
- // Other fields
- info["has_requirements"] = mHasRequirements;
- info["has_separate_specular_color"] = mHasSeparateSpecularColor;
- info["max_vertex_range"] = mGLMaxVertexRange;
- info["max_index_range"] = mGLMaxIndexRange;
- info["max_texture_size"] = mGLMaxTextureSize;
info["gl_renderer"] = mGLRenderer;
}
@@ -953,498 +1369,876 @@ void LLGLManager::shutdownGL()
void LLGLManager::initExtensions()
{
-#if LL_MESA_HEADLESS
-# ifdef GL_ARB_multitexture
- mHasMultitexture = TRUE;
-# else
- mHasMultitexture = FALSE;
-# endif // GL_ARB_multitexture
-# ifdef GL_ARB_texture_env_combine
- mHasARBEnvCombine = TRUE;
-# else
- mHasARBEnvCombine = FALSE;
-# endif // GL_ARB_texture_env_combine
-# ifdef GL_ARB_texture_compression
- mHasCompressedTextures = TRUE;
-# else
- mHasCompressedTextures = FALSE;
-# endif // GL_ARB_texture_compression
-# ifdef GL_ARB_vertex_buffer_object
- mHasVertexBufferObject = TRUE;
-# else
- mHasVertexBufferObject = FALSE;
-# endif // GL_ARB_vertex_buffer_object
-# ifdef GL_EXT_framebuffer_object
- mHasFramebufferObject = TRUE;
-# else
- mHasFramebufferObject = FALSE;
-# endif // GL_EXT_framebuffer_object
-# ifdef GL_ARB_draw_buffers
- mHasDrawBuffers = TRUE;
-#else
- mHasDrawBuffers = FALSE;
-# endif // GL_ARB_draw_buffers
-# if defined(GL_NV_depth_clamp) || defined(GL_ARB_depth_clamp)
- mHasDepthClamp = TRUE;
-#else
- mHasDepthClamp = FALSE;
-#endif // defined(GL_NV_depth_clamp) || defined(GL_ARB_depth_clamp)
-# if GL_EXT_blend_func_separate
- mHasBlendFuncSeparate = TRUE;
-#else
- mHasBlendFuncSeparate = FALSE;
-# endif // GL_EXT_blend_func_separate
- mHasMipMapGeneration = FALSE;
- mHasSeparateSpecularColor = FALSE;
- mHasAnisotropic = FALSE;
- mHasCubeMap = FALSE;
- mHasOcclusionQuery = FALSE;
- mHasPointParameters = FALSE;
- mHasTextureRectangle = FALSE;
-#else // LL_MESA_HEADLESS //important, gGLHExts.mSysExts is uninitialized until after glh_init_extensions is called
- mHasMultitexture = glh_init_extensions("GL_ARB_multitexture");
- mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts); //Basic AMD method, also see mHasAMDAssociations
- mHasNVXMemInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts);
- mHasSeparateSpecularColor = glh_init_extensions("GL_EXT_separate_specular_color");
- mHasAnisotropic = glh_init_extensions("GL_EXT_texture_filter_anisotropic");
- glh_init_extensions("GL_ARB_texture_cube_map");
- mHasCubeMap = ExtensionExists("GL_ARB_texture_cube_map", gGLHExts.mSysExts);
- mHasARBEnvCombine = ExtensionExists("GL_ARB_texture_env_combine", gGLHExts.mSysExts);
- mHasCompressedTextures = glh_init_extensions("GL_ARB_texture_compression");
- mHasOcclusionQuery = ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts);
- mHasTimerQuery = ExtensionExists("GL_ARB_timer_query", gGLHExts.mSysExts);
- mHasOcclusionQuery2 = ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts);
- mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts);
- mHasVertexArrayObject = ExtensionExists("GL_ARB_vertex_array_object", gGLHExts.mSysExts);
- mHasSync = ExtensionExists("GL_ARB_sync", gGLHExts.mSysExts);
- mHasMapBufferRange = ExtensionExists("GL_ARB_map_buffer_range", gGLHExts.mSysExts);
- mHasFlushBufferRange = ExtensionExists("GL_APPLE_flush_buffer_range", gGLHExts.mSysExts);
- // NOTE: Using extensions breaks reflections when Shadows are set to projector. See: SL-16727
- //mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts);
- mHasDepthClamp = FALSE;
- // mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad
-#ifdef GL_ARB_framebuffer_object
- mHasFramebufferObject = ExtensionExists("GL_ARB_framebuffer_object", gGLHExts.mSysExts);
-#else
- mHasFramebufferObject = ExtensionExists("GL_EXT_framebuffer_object", gGLHExts.mSysExts) &&
- ExtensionExists("GL_EXT_framebuffer_blit", gGLHExts.mSysExts) &&
- ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts) &&
- ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts);
-#endif
-#ifdef GL_EXT_texture_sRGB
- mHassRGBTexture = ExtensionExists("GL_EXT_texture_sRGB", gGLHExts.mSysExts);
-#endif
-
-#ifdef GL_ARB_framebuffer_sRGB
- mHassRGBFramebuffer = ExtensionExists("GL_ARB_framebuffer_sRGB", gGLHExts.mSysExts);
-#else
- mHassRGBFramebuffer = ExtensionExists("GL_EXT_framebuffer_sRGB", gGLHExts.mSysExts);
-#endif
-
-#ifdef GL_EXT_texture_sRGB_decode
- mHasTexturesRGBDecode = ExtensionExists("GL_EXT_texture_sRGB_decode", gGLHExts.mSysExts);
-#else
- mHasTexturesRGBDecode = ExtensionExists("GL_ARB_texture_sRGB_decode", gGLHExts.mSysExts);
-#endif
-
- mHasMipMapGeneration = mHasFramebufferObject || mGLVersion >= 1.4f;
-
- mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts);
- mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts);
- mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts);
- mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts);
- mHasDebugOutput = ExtensionExists("GL_ARB_debug_output", gGLHExts.mSysExts);
- mHasTransformFeedback = mGLVersion >= 4.f ? TRUE : FALSE;
-#if !LL_DARWIN
- mHasPointParameters = ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);
-#endif
+#if LL_DARWIN
+ GLint num_extensions = 0;
+ std::string all_extensions{""};
+ glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
+ for(GLint i = 0; i < num_extensions; ++i) {
+ char const * extension = (char const *)glGetStringi(GL_EXTENSIONS, i);
+ all_extensions += extension;
+ all_extensions += ' ';
+ }
+ if (num_extensions)
+ {
+ all_extensions += "GL_ARB_multitexture GL_ARB_texture_cube_map GL_ARB_texture_compression "; // These are in 3.2 core, but not listed by OSX
+ gGLHExts.mSysExts = strdup(all_extensions.data());
+ }
#endif
-#if LL_LINUX
- LL_INFOS() << "initExtensions() checking shell variables to adjust features..." << LL_ENDL;
- // Our extension support for the Linux Client is very young with some
- // potential driver gotchas, so offer a semi-secret way to turn it off.
- if (getenv("LL_GL_NOEXT"))
- {
- //mHasMultitexture = FALSE; // NEEDED!
- mHasDepthClamp = FALSE;
- mHasARBEnvCombine = FALSE;
- mHasCompressedTextures = FALSE;
- mHasVertexBufferObject = FALSE;
- mHasFramebufferObject = FALSE;
- mHasDrawBuffers = FALSE;
- mHasBlendFuncSeparate = FALSE;
- mHasMipMapGeneration = FALSE;
- mHasSeparateSpecularColor = FALSE;
- mHasAnisotropic = FALSE;
- mHasCubeMap = FALSE;
- mHasOcclusionQuery = FALSE;
- mHasPointParameters = FALSE;
- LL_WARNS("RenderInit") << "GL extension support DISABLED via LL_GL_NOEXT" << LL_ENDL;
- }
- else if (getenv("LL_GL_BASICEXT")) /* Flawfinder: ignore */
- {
- // This switch attempts to turn off all support for exotic
- // extensions which I believe correspond to fatal driver
- // bug reports. This should be the default until we get a
- // proper blacklist/whitelist on Linux.
- mHasMipMapGeneration = FALSE;
- mHasAnisotropic = FALSE;
- //mHasCubeMap = FALSE; // apparently fatal on Intel 915 & similar
- //mHasOcclusionQuery = FALSE; // source of many ATI system hangs
- mHasBlendFuncSeparate = FALSE;
- LL_WARNS("RenderInit") << "GL extension support forced to SIMPLE level via LL_GL_BASICEXT" << LL_ENDL;
- }
- if (getenv("LL_GL_BLACKLIST")) /* Flawfinder: ignore */
- {
- // This lets advanced troubleshooters disable specific
- // GL extensions to isolate problems with their hardware.
- // SL-28126
- const char *const blacklist = getenv("LL_GL_BLACKLIST"); /* Flawfinder: ignore */
- LL_WARNS("RenderInit") << "GL extension support partially disabled via LL_GL_BLACKLIST: " << blacklist << LL_ENDL;
- if (strchr(blacklist,'a')) mHasARBEnvCombine = FALSE;
- if (strchr(blacklist,'b')) mHasCompressedTextures = FALSE;
- if (strchr(blacklist,'c')) mHasVertexBufferObject = FALSE;
- if (strchr(blacklist,'d')) mHasMipMapGeneration = FALSE;//S
-// if (strchr(blacklist,'f')) mHasNVVertexArrayRange = FALSE;//S
-// if (strchr(blacklist,'g')) mHasNVFence = FALSE;//S
- if (strchr(blacklist,'h')) mHasSeparateSpecularColor = FALSE;
- if (strchr(blacklist,'i')) mHasAnisotropic = FALSE;//S
- if (strchr(blacklist,'j')) mHasCubeMap = FALSE;//S
-// if (strchr(blacklist,'k')) mHasATIVAO = FALSE;//S
- if (strchr(blacklist,'l')) mHasOcclusionQuery = FALSE;
- if (strchr(blacklist,'p')) mHasPointParameters = FALSE;//S
- if (strchr(blacklist,'q')) mHasFramebufferObject = FALSE;//S
- if (strchr(blacklist,'r')) mHasDrawBuffers = FALSE;//S
- if (strchr(blacklist,'s')) mHasTextureRectangle = FALSE;
- if (strchr(blacklist,'t')) mHasBlendFuncSeparate = FALSE;//S
- if (strchr(blacklist,'u')) mHasDepthClamp = FALSE;
-
- }
-#endif // LL_LINUX
-
- if (!mHasMultitexture)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize multitexturing" << LL_ENDL;
- }
- if (!mHasMipMapGeneration)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize mipmap generation" << LL_ENDL;
- }
- if (!mHasARBEnvCombine)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_texture_env_combine" << LL_ENDL;
- }
- if (!mHasSeparateSpecularColor)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize separate specular color" << LL_ENDL;
- }
- if (!mHasAnisotropic)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize anisotropic filtering" << LL_ENDL;
- }
- if (!mHasCompressedTextures)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_texture_compression" << LL_ENDL;
- }
- if (!mHasOcclusionQuery)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_occlusion_query" << LL_ENDL;
- }
- if (!mHasOcclusionQuery2)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_occlusion_query2" << LL_ENDL;
- }
- if (!mHasPointParameters)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_point_parameters" << LL_ENDL;
- }
- if (!mHasBlendFuncSeparate)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize GL_EXT_blend_func_separate" << LL_ENDL;
- }
- if (!mHasDrawBuffers)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_draw_buffers" << LL_ENDL;
- }
-
- // Disable certain things due to known bugs
- if (mIsIntel && mHasMipMapGeneration)
- {
- LL_INFOS("RenderInit") << "Disabling mip-map generation for Intel GPUs" << LL_ENDL;
- mHasMipMapGeneration = FALSE;
- }
+ // NOTE: version checks against mGLVersion should bias down by 0.01 because of F32 errors
+
+ // OpenGL 4.x capabilities
+ mHasCubeMapArray = mGLVersion >= 3.99f;
+ mHasTransformFeedback = mGLVersion >= 3.99f;
+ mHasDebugOutput = mGLVersion >= 4.29f;
- // Misc
+ // Misc
glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*) &mGLMaxVertexRange);
glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*) &mGLMaxIndexRange);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*) &mGLMaxTextureSize);
+ mInited = TRUE;
+
#if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS
LL_DEBUGS("RenderInit") << "GL Probe: Getting symbols" << LL_ENDL;
- if (mHasVertexBufferObject)
- {
- glBindBufferARB = (PFNGLBINDBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBindBufferARB");
- if (glBindBufferARB)
- {
- glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteBuffersARB");
- glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGenBuffersARB");
- glIsBufferARB = (PFNGLISBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("glIsBufferARB");
- glBufferDataARB = (PFNGLBUFFERDATAARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBufferDataARB");
- glBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBufferSubDataARB");
- glGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferSubDataARB");
- glMapBufferARB = (PFNGLMAPBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMapBufferARB");
- glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("glUnmapBufferARB");
- glGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferParameterivARB");
- glGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferPointervARB");
- }
- else
- {
- mHasVertexBufferObject = FALSE;
- }
- }
- if (mHasVertexArrayObject)
- {
- glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) GLH_EXT_GET_PROC_ADDRESS("glBindVertexArray");
- glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteVertexArrays");
- glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) GLH_EXT_GET_PROC_ADDRESS("glGenVertexArrays");
- glIsVertexArray = (PFNGLISVERTEXARRAYPROC) GLH_EXT_GET_PROC_ADDRESS("glIsVertexArray");
- }
- if (mHasSync)
- {
- glFenceSync = (PFNGLFENCESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glFenceSync");
- glIsSync = (PFNGLISSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glIsSync");
- glDeleteSync = (PFNGLDELETESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteSync");
- glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glClientWaitSync");
- glWaitSync = (PFNGLWAITSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glWaitSync");
- glGetInteger64v = (PFNGLGETINTEGER64VPROC) GLH_EXT_GET_PROC_ADDRESS("glGetInteger64v");
- glGetSynciv = (PFNGLGETSYNCIVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetSynciv");
- }
- if (mHasMapBufferRange)
- {
- glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glMapBufferRange");
- glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glFlushMappedBufferRange");
- }
- if (mHasFramebufferObject)
- {
- LL_INFOS() << "initExtensions() FramebufferObject-related procs..." << LL_ENDL;
- glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glIsRenderbuffer");
- glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glBindRenderbuffer");
- glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteRenderbuffers");
- glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) GLH_EXT_GET_PROC_ADDRESS("glGenRenderbuffers");
- glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorage");
- glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetRenderbufferParameteriv");
- glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glIsFramebuffer");
- glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glBindFramebuffer");
- glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteFramebuffers");
- glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) GLH_EXT_GET_PROC_ADDRESS("glGenFramebuffers");
- glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) GLH_EXT_GET_PROC_ADDRESS("glCheckFramebufferStatus");
- glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture1D");
- glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture2D");
- glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture3D");
- glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferRenderbuffer");
- glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetFramebufferAttachmentParameteriv");
- glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) GLH_EXT_GET_PROC_ADDRESS("glGenerateMipmap");
- glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glBlitFramebuffer");
- glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorageMultisample");
- glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTextureLayer");
- }
- if (mHasDrawBuffers)
- {
- glDrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDrawBuffersARB");
- }
- if (mHasBlendFuncSeparate)
- {
- glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlendFuncSeparateEXT");
- }
- if (mHasTextureMultisample)
- {
- glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage2DMultisample");
- glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage3DMultisample");
- glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv");
- glSampleMaski = (PFNGLSAMPLEMASKIPROC) GLH_EXT_GET_PROC_ADDRESS("glSampleMaski");
- }
- if (mHasTransformFeedback)
- {
- glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glBeginTransformFeedback");
- glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glEndTransformFeedback");
- glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackVaryings");
- glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferRange");
- glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferBase");
- }
- if (mHasDebugOutput)
- {
- glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageControlARB");
- glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageInsertARB");
- glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageCallbackARB");
- glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetDebugMessageLogARB");
- }
-#if (!LL_LINUX) || LL_LINUX_NV_GL_HEADERS
- // This is expected to be a static symbol on Linux GL implementations, except if we use the nvidia headers - bah
- glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements");
- if (!glDrawRangeElements)
- {
- mGLMaxVertexRange = 0;
- mGLMaxIndexRange = 0;
- }
-#endif // !LL_LINUX || LL_LINUX_NV_GL_HEADERS
-#if LL_LINUX_NV_GL_HEADERS
- // nvidia headers are critically different from mesa-esque
- glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS("glActiveTextureARB");
- glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS("glClientActiveTextureARB");
-#endif // LL_LINUX_NV_GL_HEADERS
-
- if (mHasOcclusionQuery)
- {
- LL_INFOS() << "initExtensions() OcclusionQuery-related procs..." << LL_ENDL;
- glGenQueriesARB = (PFNGLGENQUERIESARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGenQueriesARB");
- glDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteQueriesARB");
- glIsQueryARB = (PFNGLISQUERYARBPROC)GLH_EXT_GET_PROC_ADDRESS("glIsQueryARB");
- glBeginQueryARB = (PFNGLBEGINQUERYARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBeginQueryARB");
- glEndQueryARB = (PFNGLENDQUERYARBPROC)GLH_EXT_GET_PROC_ADDRESS("glEndQueryARB");
- glGetQueryivARB = (PFNGLGETQUERYIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryivARB");
- glGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectivARB");
- glGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectuivARB");
- }
- if (mHasTimerQuery)
- {
- LL_INFOS() << "initExtensions() TimerQuery-related procs..." << LL_ENDL;
- glQueryCounter = (PFNGLQUERYCOUNTERPROC) GLH_EXT_GET_PROC_ADDRESS("glQueryCounter");
- glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC) GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjecti64v");
- glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC) GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectui64v");
- }
- if (mHasPointParameters)
- {
- LL_INFOS() << "initExtensions() PointParameters-related procs..." << LL_ENDL;
- glPointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfARB");
- glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfvARB");
- }
-
- // Assume shader capabilities
- glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteObjectARB");
- glGetHandleARB = (PFNGLGETHANDLEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetHandleARB");
- glDetachObjectARB = (PFNGLDETACHOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDetachObjectARB");
- glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCreateShaderObjectARB");
- glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glShaderSourceARB");
- glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCompileShaderARB");
- glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCreateProgramObjectARB");
- glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glAttachObjectARB");
- glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glLinkProgramARB");
- glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUseProgramObjectARB");
- glValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glValidateProgramARB");
- glUniform1fARB = (PFNGLUNIFORM1FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1fARB");
- glUniform2fARB = (PFNGLUNIFORM2FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2fARB");
- glUniform3fARB = (PFNGLUNIFORM3FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3fARB");
- glUniform4fARB = (PFNGLUNIFORM4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4fARB");
- glUniform1iARB = (PFNGLUNIFORM1IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1iARB");
- glUniform2iARB = (PFNGLUNIFORM2IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2iARB");
- glUniform3iARB = (PFNGLUNIFORM3IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3iARB");
- glUniform4iARB = (PFNGLUNIFORM4IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4iARB");
- glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1fvARB");
- glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2fvARB");
- glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3fvARB");
- glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4fvARB");
- glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1ivARB");
- glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2ivARB");
- glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3ivARB");
- glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4ivARB");
- glUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2fvARB");
- glUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3fvARB");
- glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3x4fv");
- glUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4fvARB");
- glGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetObjectParameterfvARB");
- glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetObjectParameterivARB");
- glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetInfoLogARB");
- glGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttachedObjectsARB");
- glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformLocationARB");
- glGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformARB");
- glGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformfvARB");
- glGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformivARB");
- glGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetShaderSourceARB");
-
- LL_INFOS() << "initExtensions() VertexShader-related procs..." << LL_ENDL;
-
- // nSight doesn't support use of ARB funcs that have been normalized in the API
- if (!LLRender::sNsightDebugSupport)
+
+#if LL_WINDOWS
+ // WGL_AMD_gpu_association
+ wglGetGPUIDsAMD = (PFNWGLGETGPUIDSAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUIDsAMD");
+ wglGetGPUInfoAMD = (PFNWGLGETGPUINFOAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUInfoAMD");
+ wglGetContextGPUIDAMD = (PFNWGLGETCONTEXTGPUIDAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetContextGPUIDAMD");
+ wglCreateAssociatedContextAMD = (PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglCreateAssociatedContextAMD");
+ wglCreateAssociatedContextAttribsAMD = (PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglCreateAssociatedContextAttribsAMD");
+ wglDeleteAssociatedContextAMD = (PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglDeleteAssociatedContextAMD");
+ wglMakeAssociatedContextCurrentAMD = (PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglMakeAssociatedContextCurrentAMD");
+ wglGetCurrentAssociatedContextAMD = (PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetCurrentAssociatedContextAMD");
+ wglBlitContextFramebufferAMD = (PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglBlitContextFramebufferAMD");
+
+ // WGL_EXT_swap_control
+ wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)GLH_EXT_GET_PROC_ADDRESS("wglSwapIntervalEXT");
+ wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetSwapIntervalEXT");
+
+ // WGL_ARB_create_context
+ wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglCreateContextAttribsARB");
+#endif
+
+
+ // Load entire OpenGL API through GetProcAddress, leaving sections beyond mGLVersion unloaded
+
+ // GL_VERSION_1_2
+ if (mGLVersion < 1.19f)
{
- glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocationARB");
- glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocationARB");
+ return;
}
- else
+ glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements");
+ glTexImage3D = (PFNGLTEXIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glTexImage3D");
+ glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glTexSubImage3D");
+ glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyTexSubImage3D");
+
+
+ // GL_VERSION_1_3
+ if (mGLVersion < 1.29f)
{
- glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocation");
- glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocation");
+ return;
}
-
- glGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveAttribARB");
- glVertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dARB");
- glVertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dvARB");
- glVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fARB");
- glVertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fvARB");
- glVertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1sARB");
- glVertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1svARB");
- glVertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dARB");
- glVertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dvARB");
- glVertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fARB");
- glVertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fvARB");
- glVertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2sARB");
- glVertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2svARB");
- glVertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dARB");
- glVertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dvARB");
- glVertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fARB");
- glVertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fvARB");
- glVertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3sARB");
- glVertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3svARB");
- glVertexAttrib4nbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nbvARB");
- glVertexAttrib4nivARB = (PFNGLVERTEXATTRIB4NIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nivARB");
- glVertexAttrib4nsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nsvARB");
- glVertexAttrib4nubARB = (PFNGLVERTEXATTRIB4NUBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nubARB");
- glVertexAttrib4nubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nubvARB");
- glVertexAttrib4nuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nuivARB");
- glVertexAttrib4nusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nusvARB");
- glVertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4bvARB");
- glVertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dARB");
- glVertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dvARB");
- glVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fARB");
- glVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fvARB");
- glVertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ivARB");
- glVertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4sARB");
- glVertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4svARB");
- glVertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ubvARB");
- glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4uivARB");
- glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4usvARB");
- glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribPointerARB");
- glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribIPointer");
- glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glEnableVertexAttribArrayARB");
- glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDisableVertexAttribArrayARB");
- glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramStringARB");
- glBindProgramARB = (PFNGLBINDPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindProgramARB");
- glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteProgramsARB");
- glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGenProgramsARB");
- glProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dARB");
- glProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dvARB");
- glProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fARB");
- glProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fvARB");
- glProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dARB");
- glProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dvARB");
- glProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fARB");
- glProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fvARB");
- glGetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterdvARB");
- glGetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterfvARB");
- glGetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterdvARB");
- glGetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterfvARB");
- glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramivARB");
- glGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramStringARB");
- glGetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribdvARB");
- glGetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribfvARB");
- glGetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribivARB");
- glGetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glgetVertexAttribPointervARB");
- glIsProgramARB = (PFNGLISPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glIsProgramARB");
-
- LL_DEBUGS("RenderInit") << "GL Probe: Got symbols" << LL_ENDL;
+ glActiveTexture = (PFNGLACTIVETEXTUREPROC)GLH_EXT_GET_PROC_ADDRESS("glActiveTexture");
+ glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glSampleCoverage");
+ glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexImage3D");
+ glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexImage2D");
+ glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexImage1D");
+ glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexSubImage3D");
+ glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexSubImage2D");
+ glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexSubImage1D");
+ glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetCompressedTexImage");
+ glClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC)GLH_EXT_GET_PROC_ADDRESS("glClientActiveTexture");
+ glMultiTexCoord1d = (PFNGLMULTITEXCOORD1DPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1d");
+ glMultiTexCoord1dv = (PFNGLMULTITEXCOORD1DVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1dv");
+ glMultiTexCoord1f = (PFNGLMULTITEXCOORD1FPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1f");
+ glMultiTexCoord1fv = (PFNGLMULTITEXCOORD1FVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1fv");
+ glMultiTexCoord1i = (PFNGLMULTITEXCOORD1IPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1i");
+ glMultiTexCoord1iv = (PFNGLMULTITEXCOORD1IVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1iv");
+ glMultiTexCoord1s = (PFNGLMULTITEXCOORD1SPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1s");
+ glMultiTexCoord1sv = (PFNGLMULTITEXCOORD1SVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1sv");
+ glMultiTexCoord2d = (PFNGLMULTITEXCOORD2DPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2d");
+ glMultiTexCoord2dv = (PFNGLMULTITEXCOORD2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2dv");
+ glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2f");
+ glMultiTexCoord2fv = (PFNGLMULTITEXCOORD2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2fv");
+ glMultiTexCoord2i = (PFNGLMULTITEXCOORD2IPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2i");
+ glMultiTexCoord2iv = (PFNGLMULTITEXCOORD2IVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2iv");
+ glMultiTexCoord2s = (PFNGLMULTITEXCOORD2SPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2s");
+ glMultiTexCoord2sv = (PFNGLMULTITEXCOORD2SVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2sv");
+ glMultiTexCoord3d = (PFNGLMULTITEXCOORD3DPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3d");
+ glMultiTexCoord3dv = (PFNGLMULTITEXCOORD3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3dv");
+ glMultiTexCoord3f = (PFNGLMULTITEXCOORD3FPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3f");
+ glMultiTexCoord3fv = (PFNGLMULTITEXCOORD3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3fv");
+ glMultiTexCoord3i = (PFNGLMULTITEXCOORD3IPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3i");
+ glMultiTexCoord3iv = (PFNGLMULTITEXCOORD3IVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3iv");
+ glMultiTexCoord3s = (PFNGLMULTITEXCOORD3SPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3s");
+ glMultiTexCoord3sv = (PFNGLMULTITEXCOORD3SVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3sv");
+ glMultiTexCoord4d = (PFNGLMULTITEXCOORD4DPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4d");
+ glMultiTexCoord4dv = (PFNGLMULTITEXCOORD4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4dv");
+ glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4f");
+ glMultiTexCoord4fv = (PFNGLMULTITEXCOORD4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4fv");
+ glMultiTexCoord4i = (PFNGLMULTITEXCOORD4IPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4i");
+ glMultiTexCoord4iv = (PFNGLMULTITEXCOORD4IVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4iv");
+ glMultiTexCoord4s = (PFNGLMULTITEXCOORD4SPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4s");
+ glMultiTexCoord4sv = (PFNGLMULTITEXCOORD4SVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4sv");
+ glLoadTransposeMatrixf = (PFNGLLOADTRANSPOSEMATRIXFPROC)GLH_EXT_GET_PROC_ADDRESS("glLoadTransposeMatrixf");
+ glLoadTransposeMatrixd = (PFNGLLOADTRANSPOSEMATRIXDPROC)GLH_EXT_GET_PROC_ADDRESS("glLoadTransposeMatrixd");
+ glMultTransposeMatrixf = (PFNGLMULTTRANSPOSEMATRIXFPROC)GLH_EXT_GET_PROC_ADDRESS("glMultTransposeMatrixf");
+ glMultTransposeMatrixd = (PFNGLMULTTRANSPOSEMATRIXDPROC)GLH_EXT_GET_PROC_ADDRESS("glMultTransposeMatrixd");
+
+ // GL_VERSION_1_4
+ if (mGLVersion < 1.39f)
+ {
+ return;
+ }
+ glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendFuncSeparate");
+ glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiDrawArrays");
+ glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiDrawElements");
+ glPointParameterf = (PFNGLPOINTPARAMETERFPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterf");
+ glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfv");
+ glPointParameteri = (PFNGLPOINTPARAMETERIPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameteri");
+ glPointParameteriv = (PFNGLPOINTPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameteriv");
+ glFogCoordf = (PFNGLFOGCOORDFPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoordf");
+ glFogCoordfv = (PFNGLFOGCOORDFVPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoordfv");
+ glFogCoordd = (PFNGLFOGCOORDDPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoordd");
+ glFogCoorddv = (PFNGLFOGCOORDDVPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoorddv");
+ glFogCoordPointer = (PFNGLFOGCOORDPOINTERPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoordPointer");
+ glSecondaryColor3b = (PFNGLSECONDARYCOLOR3BPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3b");
+ glSecondaryColor3bv = (PFNGLSECONDARYCOLOR3BVPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3bv");
+ glSecondaryColor3d = (PFNGLSECONDARYCOLOR3DPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3d");
+ glSecondaryColor3dv = (PFNGLSECONDARYCOLOR3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3dv");
+ glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3f");
+ glSecondaryColor3fv = (PFNGLSECONDARYCOLOR3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3fv");
+ glSecondaryColor3i = (PFNGLSECONDARYCOLOR3IPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3i");
+ glSecondaryColor3iv = (PFNGLSECONDARYCOLOR3IVPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3iv");
+ glSecondaryColor3s = (PFNGLSECONDARYCOLOR3SPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3s");
+ glSecondaryColor3sv = (PFNGLSECONDARYCOLOR3SVPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3sv");
+ glSecondaryColor3ub = (PFNGLSECONDARYCOLOR3UBPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3ub");
+ glSecondaryColor3ubv = (PFNGLSECONDARYCOLOR3UBVPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3ubv");
+ glSecondaryColor3ui = (PFNGLSECONDARYCOLOR3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3ui");
+ glSecondaryColor3uiv = (PFNGLSECONDARYCOLOR3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3uiv");
+ glSecondaryColor3us = (PFNGLSECONDARYCOLOR3USPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3us");
+ glSecondaryColor3usv = (PFNGLSECONDARYCOLOR3USVPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3usv");
+ glSecondaryColorPointer = (PFNGLSECONDARYCOLORPOINTERPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColorPointer");
+ glWindowPos2d = (PFNGLWINDOWPOS2DPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos2d");
+ glWindowPos2dv = (PFNGLWINDOWPOS2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos2dv");
+ glWindowPos2f = (PFNGLWINDOWPOS2FPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos2f");
+ glWindowPos2fv = (PFNGLWINDOWPOS2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos2fv");
+ glWindowPos2i = (PFNGLWINDOWPOS2IPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos2i");
+ glWindowPos2iv = (PFNGLWINDOWPOS2IVPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos2iv");
+ glWindowPos2s = (PFNGLWINDOWPOS2SPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos2s");
+ glWindowPos2sv = (PFNGLWINDOWPOS2SVPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos2sv");
+ glWindowPos3d = (PFNGLWINDOWPOS3DPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos3d");
+ glWindowPos3dv = (PFNGLWINDOWPOS3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos3dv");
+ glWindowPos3f = (PFNGLWINDOWPOS3FPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos3f");
+ glWindowPos3fv = (PFNGLWINDOWPOS3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos3fv");
+ glWindowPos3i = (PFNGLWINDOWPOS3IPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos3i");
+ glWindowPos3iv = (PFNGLWINDOWPOS3IVPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos3iv");
+ glWindowPos3s = (PFNGLWINDOWPOS3SPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos3s");
+ glWindowPos3sv = (PFNGLWINDOWPOS3SVPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos3sv");
+
+ // GL_VERSION_1_5
+ if (mGLVersion < 1.49f)
+ {
+ return;
+ }
+ glGenQueries = (PFNGLGENQUERIESPROC)GLH_EXT_GET_PROC_ADDRESS("glGenQueries");
+ glDeleteQueries = (PFNGLDELETEQUERIESPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteQueries");
+ glIsQuery = (PFNGLISQUERYPROC)GLH_EXT_GET_PROC_ADDRESS("glIsQuery");
+ glBeginQuery = (PFNGLBEGINQUERYPROC)GLH_EXT_GET_PROC_ADDRESS("glBeginQuery");
+ glEndQuery = (PFNGLENDQUERYPROC)GLH_EXT_GET_PROC_ADDRESS("glEndQuery");
+ glGetQueryiv = (PFNGLGETQUERYIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryiv");
+ glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectiv");
+ glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectuiv");
+ glBindBuffer = (PFNGLBINDBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glBindBuffer");
+ glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteBuffers");
+ glGenBuffers = (PFNGLGENBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glGenBuffers");
+ glIsBuffer = (PFNGLISBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glIsBuffer");
+ glBufferData = (PFNGLBUFFERDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glBufferData");
+ glBufferSubData = (PFNGLBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glBufferSubData");
+ glGetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferSubData");
+ glMapBuffer = (PFNGLMAPBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glMapBuffer");
+ glUnmapBuffer = (PFNGLUNMAPBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glUnmapBuffer");
+ glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferParameteriv");
+ glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferPointerv");
+
+ // GL_VERSION_2_0
+ if (mGLVersion < 1.9f)
+ {
+ return;
+ }
+ glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendEquationSeparate");
+ glDrawBuffers = (PFNGLDRAWBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawBuffers");
+ glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)GLH_EXT_GET_PROC_ADDRESS("glStencilOpSeparate");
+ glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC)GLH_EXT_GET_PROC_ADDRESS("glStencilFuncSeparate");
+ glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC)GLH_EXT_GET_PROC_ADDRESS("glStencilMaskSeparate");
+ glAttachShader = (PFNGLATTACHSHADERPROC)GLH_EXT_GET_PROC_ADDRESS("glAttachShader");
+ glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocation");
+ glCompileShader = (PFNGLCOMPILESHADERPROC)GLH_EXT_GET_PROC_ADDRESS("glCompileShader");
+ glCreateProgram = (PFNGLCREATEPROGRAMPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateProgram");
+ glCreateShader = (PFNGLCREATESHADERPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateShader");
+ glDeleteProgram = (PFNGLDELETEPROGRAMPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteProgram");
+ glDeleteShader = (PFNGLDELETESHADERPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteShader");
+ glDetachShader = (PFNGLDETACHSHADERPROC)GLH_EXT_GET_PROC_ADDRESS("glDetachShader");
+ glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)GLH_EXT_GET_PROC_ADDRESS("glDisableVertexAttribArray");
+ glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)GLH_EXT_GET_PROC_ADDRESS("glEnableVertexAttribArray");
+ glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveAttrib");
+ glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniform");
+ glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC)GLH_EXT_GET_PROC_ADDRESS("glGetAttachedShaders");
+ glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocation");
+ glGetProgramiv = (PFNGLGETPROGRAMIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramiv");
+ glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramInfoLog");
+ glGetShaderiv = (PFNGLGETSHADERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetShaderiv");
+ glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)GLH_EXT_GET_PROC_ADDRESS("glGetShaderInfoLog");
+ glGetShaderSource = (PFNGLGETSHADERSOURCEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetShaderSource");
+ glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformLocation");
+ glGetUniformfv = (PFNGLGETUNIFORMFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformfv");
+ glGetUniformiv = (PFNGLGETUNIFORMIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformiv");
+ glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribdv");
+ glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribfv");
+ glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribiv");
+ glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribPointerv");
+ glIsProgram = (PFNGLISPROGRAMPROC)GLH_EXT_GET_PROC_ADDRESS("glIsProgram");
+ glIsShader = (PFNGLISSHADERPROC)GLH_EXT_GET_PROC_ADDRESS("glIsShader");
+ glLinkProgram = (PFNGLLINKPROGRAMPROC)GLH_EXT_GET_PROC_ADDRESS("glLinkProgram");
+ glShaderSource = (PFNGLSHADERSOURCEPROC)GLH_EXT_GET_PROC_ADDRESS("glShaderSource");
+ glUseProgram = (PFNGLUSEPROGRAMPROC)GLH_EXT_GET_PROC_ADDRESS("glUseProgram");
+ glUniform1f = (PFNGLUNIFORM1FPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform1f");
+ glUniform2f = (PFNGLUNIFORM2FPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform2f");
+ glUniform3f = (PFNGLUNIFORM3FPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform3f");
+ glUniform4f = (PFNGLUNIFORM4FPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform4f");
+ glUniform1i = (PFNGLUNIFORM1IPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform1i");
+ glUniform2i = (PFNGLUNIFORM2IPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform2i");
+ glUniform3i = (PFNGLUNIFORM3IPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform3i");
+ glUniform4i = (PFNGLUNIFORM4IPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform4i");
+ glUniform1fv = (PFNGLUNIFORM1FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform1fv");
+ glUniform2fv = (PFNGLUNIFORM2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform2fv");
+ glUniform3fv = (PFNGLUNIFORM3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform3fv");
+ glUniform4fv = (PFNGLUNIFORM4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform4fv");
+ glUniform1iv = (PFNGLUNIFORM1IVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform1iv");
+ glUniform2iv = (PFNGLUNIFORM2IVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform2iv");
+ glUniform3iv = (PFNGLUNIFORM3IVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform3iv");
+ glUniform4iv = (PFNGLUNIFORM4IVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform4iv");
+ glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2fv");
+ glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3fv");
+ glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4fv");
+ glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)GLH_EXT_GET_PROC_ADDRESS("glValidateProgram");
+ glVertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1d");
+ glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dv");
+ glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1f");
+ glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fv");
+ glVertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1s");
+ glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1sv");
+ glVertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2d");
+ glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dv");
+ glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2f");
+ glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fv");
+ glVertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2s");
+ glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2sv");
+ glVertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3d");
+ glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dv");
+ glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3f");
+ glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fv");
+ glVertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3s");
+ glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3sv");
+ glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4Nbv");
+ glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4Niv");
+ glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4Nsv");
+ glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4Nub");
+ glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4Nubv");
+ glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4Nuiv");
+ glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4Nusv");
+ glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4bv");
+ glVertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4d");
+ glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dv");
+ glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4f");
+ glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fv");
+ glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4iv");
+ glVertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4s");
+ glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4sv");
+ glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ubv");
+ glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4uiv");
+ glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4usv");
+ glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribPointer");
+
+ // GL_VERSION_2_1
+ if (mGLVersion < 2.09f)
+ {
+ return;
+ }
+ glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2x3fv");
+ glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3x2fv");
+ glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2x4fv");
+ glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4x2fv");
+ glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3x4fv");
+ glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4x3fv");
+
+ // GL_VERSION_3_0
+ if (mGLVersion < 2.99f)
+ {
+ return;
+ }
+ glColorMaski = (PFNGLCOLORMASKIPROC)GLH_EXT_GET_PROC_ADDRESS("glColorMaski");
+ glGetBooleani_v = (PFNGLGETBOOLEANI_VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBooleani_v");
+ glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetIntegeri_v");
+ glEnablei = (PFNGLENABLEIPROC)GLH_EXT_GET_PROC_ADDRESS("glEnablei");
+ glDisablei = (PFNGLDISABLEIPROC)GLH_EXT_GET_PROC_ADDRESS("glDisablei");
+ glIsEnabledi = (PFNGLISENABLEDIPROC)GLH_EXT_GET_PROC_ADDRESS("glIsEnabledi");
+ glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC)GLH_EXT_GET_PROC_ADDRESS("glBeginTransformFeedback");
+ glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC)GLH_EXT_GET_PROC_ADDRESS("glEndTransformFeedback");
+ glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC)GLH_EXT_GET_PROC_ADDRESS("glBindBufferRange");
+ glBindBufferBase = (PFNGLBINDBUFFERBASEPROC)GLH_EXT_GET_PROC_ADDRESS("glBindBufferBase");
+ glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC)GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackVaryings");
+ glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTransformFeedbackVarying");
+ glClampColor = (PFNGLCLAMPCOLORPROC)GLH_EXT_GET_PROC_ADDRESS("glClampColor");
+ glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC)GLH_EXT_GET_PROC_ADDRESS("glBeginConditionalRender");
+ glEndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC)GLH_EXT_GET_PROC_ADDRESS("glEndConditionalRender");
+ glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribIPointer");
+ glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribIiv");
+ glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribIuiv");
+ glVertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI1i");
+ glVertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI2i");
+ glVertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI3i");
+ glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI4i");
+ glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI1ui");
+ glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI2ui");
+ glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI3ui");
+ glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI4ui");
+ glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI1iv");
+ glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI2iv");
+ glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI3iv");
+ glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI4iv");
+ glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI1uiv");
+ glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI2uiv");
+ glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI3uiv");
+ glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI4uiv");
+ glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI4bv");
+ glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI4sv");
+ glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI4ubv");
+ glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI4usv");
+ glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformuiv");
+ glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC)GLH_EXT_GET_PROC_ADDRESS("glBindFragDataLocation");
+ glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC)GLH_EXT_GET_PROC_ADDRESS("glGetFragDataLocation");
+ glUniform1ui = (PFNGLUNIFORM1UIPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform1ui");
+ glUniform2ui = (PFNGLUNIFORM2UIPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform2ui");
+ glUniform3ui = (PFNGLUNIFORM3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform3ui");
+ glUniform4ui = (PFNGLUNIFORM4UIPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform4ui");
+ glUniform1uiv = (PFNGLUNIFORM1UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform1uiv");
+ glUniform2uiv = (PFNGLUNIFORM2UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform2uiv");
+ glUniform3uiv = (PFNGLUNIFORM3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform3uiv");
+ glUniform4uiv = (PFNGLUNIFORM4UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform4uiv");
+ glTexParameterIiv = (PFNGLTEXPARAMETERIIVPROC)GLH_EXT_GET_PROC_ADDRESS("glTexParameterIiv");
+ glTexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glTexParameterIuiv");
+ glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTexParameterIiv");
+ glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTexParameterIuiv");
+ glClearBufferiv = (PFNGLCLEARBUFFERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glClearBufferiv");
+ glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glClearBufferuiv");
+ glClearBufferfv = (PFNGLCLEARBUFFERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glClearBufferfv");
+ glClearBufferfi = (PFNGLCLEARBUFFERFIPROC)GLH_EXT_GET_PROC_ADDRESS("glClearBufferfi");
+ glGetStringi = (PFNGLGETSTRINGIPROC)GLH_EXT_GET_PROC_ADDRESS("glGetStringi");
+ glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glIsRenderbuffer");
+ glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glBindRenderbuffer");
+ glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteRenderbuffers");
+ glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glGenRenderbuffers");
+ glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorage");
+ glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetRenderbufferParameteriv");
+ glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glIsFramebuffer");
+ glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glBindFramebuffer");
+ glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteFramebuffers");
+ glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glGenFramebuffers");
+ glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)GLH_EXT_GET_PROC_ADDRESS("glCheckFramebufferStatus");
+ glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture1D");
+ glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture2D");
+ glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture3D");
+ glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glFramebufferRenderbuffer");
+ glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetFramebufferAttachmentParameteriv");
+ glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)GLH_EXT_GET_PROC_ADDRESS("glGenerateMipmap");
+ glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glBlitFramebuffer");
+ glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorageMultisample");
+ glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)GLH_EXT_GET_PROC_ADDRESS("glFramebufferTextureLayer");
+ glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC)GLH_EXT_GET_PROC_ADDRESS("glMapBufferRange");
+ glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC)GLH_EXT_GET_PROC_ADDRESS("glFlushMappedBufferRange");
+ glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)GLH_EXT_GET_PROC_ADDRESS("glBindVertexArray");
+ glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteVertexArrays");
+ glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)GLH_EXT_GET_PROC_ADDRESS("glGenVertexArrays");
+ glIsVertexArray = (PFNGLISVERTEXARRAYPROC)GLH_EXT_GET_PROC_ADDRESS("glIsVertexArray");
+
+ // GL_VERSION_3_1
+ if (mGLVersion < 3.09f)
+ {
+ return;
+ }
+ glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawArraysInstanced");
+ glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawElementsInstanced");
+ glTexBuffer = (PFNGLTEXBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glTexBuffer");
+ glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC)GLH_EXT_GET_PROC_ADDRESS("glPrimitiveRestartIndex");
+ glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyBufferSubData");
+ glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformIndices");
+ glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformsiv");
+ glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformName");
+ glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformBlockIndex");
+ glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformBlockiv");
+ glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformBlockName");
+ glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformBlockBinding");
+
+ // GL_VERSION_3_2
+ if (mGLVersion < 3.19f)
+ {
+ return;
+ }
+ glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawElementsBaseVertex");
+ glDrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElementsBaseVertex");
+ glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawElementsInstancedBaseVertex");
+ glMultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiDrawElementsBaseVertex");
+ glProvokingVertex = (PFNGLPROVOKINGVERTEXPROC)GLH_EXT_GET_PROC_ADDRESS("glProvokingVertex");
+ glFenceSync = (PFNGLFENCESYNCPROC)GLH_EXT_GET_PROC_ADDRESS("glFenceSync");
+ glIsSync = (PFNGLISSYNCPROC)GLH_EXT_GET_PROC_ADDRESS("glIsSync");
+ glDeleteSync = (PFNGLDELETESYNCPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteSync");
+ glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC)GLH_EXT_GET_PROC_ADDRESS("glClientWaitSync");
+ glWaitSync = (PFNGLWAITSYNCPROC)GLH_EXT_GET_PROC_ADDRESS("glWaitSync");
+ glGetInteger64v = (PFNGLGETINTEGER64VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetInteger64v");
+ glGetSynciv = (PFNGLGETSYNCIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetSynciv");
+ glGetInteger64i_v = (PFNGLGETINTEGER64I_VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetInteger64i_v");
+ glGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferParameteri64v");
+ glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC)GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture");
+ glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC)GLH_EXT_GET_PROC_ADDRESS("glTexImage2DMultisample");
+ glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC)GLH_EXT_GET_PROC_ADDRESS("glTexImage3DMultisample");
+ glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv");
+ glSampleMaski = (PFNGLSAMPLEMASKIPROC)GLH_EXT_GET_PROC_ADDRESS("glSampleMaski");
+
+ // GL_VERSION_3_3
+ if (mGLVersion < 3.29f)
+ {
+ return;
+ }
+ glBindFragDataLocationIndexed = (PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)GLH_EXT_GET_PROC_ADDRESS("glBindFragDataLocationIndexed");
+ glGetFragDataIndex = (PFNGLGETFRAGDATAINDEXPROC)GLH_EXT_GET_PROC_ADDRESS("glGetFragDataIndex");
+ glGenSamplers = (PFNGLGENSAMPLERSPROC)GLH_EXT_GET_PROC_ADDRESS("glGenSamplers");
+ glDeleteSamplers = (PFNGLDELETESAMPLERSPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteSamplers");
+ glIsSampler = (PFNGLISSAMPLERPROC)GLH_EXT_GET_PROC_ADDRESS("glIsSampler");
+ glBindSampler = (PFNGLBINDSAMPLERPROC)GLH_EXT_GET_PROC_ADDRESS("glBindSampler");
+ glSamplerParameteri = (PFNGLSAMPLERPARAMETERIPROC)GLH_EXT_GET_PROC_ADDRESS("glSamplerParameteri");
+ glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glSamplerParameteriv");
+ glSamplerParameterf = (PFNGLSAMPLERPARAMETERFPROC)GLH_EXT_GET_PROC_ADDRESS("glSamplerParameterf");
+ glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glSamplerParameterfv");
+ glSamplerParameterIiv = (PFNGLSAMPLERPARAMETERIIVPROC)GLH_EXT_GET_PROC_ADDRESS("glSamplerParameterIiv");
+ glSamplerParameterIuiv = (PFNGLSAMPLERPARAMETERIUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glSamplerParameterIuiv");
+ glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetSamplerParameteriv");
+ glGetSamplerParameterIiv = (PFNGLGETSAMPLERPARAMETERIIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetSamplerParameterIiv");
+ glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetSamplerParameterfv");
+ glGetSamplerParameterIuiv = (PFNGLGETSAMPLERPARAMETERIUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetSamplerParameterIuiv");
+ glQueryCounter = (PFNGLQUERYCOUNTERPROC)GLH_EXT_GET_PROC_ADDRESS("glQueryCounter");
+ glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjecti64v");
+ glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectui64v");
+ glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribDivisor");
+ glVertexAttribP1ui = (PFNGLVERTEXATTRIBP1UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribP1ui");
+ glVertexAttribP1uiv = (PFNGLVERTEXATTRIBP1UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribP1uiv");
+ glVertexAttribP2ui = (PFNGLVERTEXATTRIBP2UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribP2ui");
+ glVertexAttribP2uiv = (PFNGLVERTEXATTRIBP2UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribP2uiv");
+ glVertexAttribP3ui = (PFNGLVERTEXATTRIBP3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribP3ui");
+ glVertexAttribP3uiv = (PFNGLVERTEXATTRIBP3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribP3uiv");
+ glVertexAttribP4ui = (PFNGLVERTEXATTRIBP4UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribP4ui");
+ glVertexAttribP4uiv = (PFNGLVERTEXATTRIBP4UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribP4uiv");
+ glVertexP2ui = (PFNGLVERTEXP2UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexP2ui");
+ glVertexP2uiv = (PFNGLVERTEXP2UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexP2uiv");
+ glVertexP3ui = (PFNGLVERTEXP3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexP3ui");
+ glVertexP3uiv = (PFNGLVERTEXP3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexP3uiv");
+ glVertexP4ui = (PFNGLVERTEXP4UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexP4ui");
+ glVertexP4uiv = (PFNGLVERTEXP4UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexP4uiv");
+ glTexCoordP1ui = (PFNGLTEXCOORDP1UIPROC)GLH_EXT_GET_PROC_ADDRESS("glTexCoordP1ui");
+ glTexCoordP1uiv = (PFNGLTEXCOORDP1UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glTexCoordP1uiv");
+ glTexCoordP2ui = (PFNGLTEXCOORDP2UIPROC)GLH_EXT_GET_PROC_ADDRESS("glTexCoordP2ui");
+ glTexCoordP2uiv = (PFNGLTEXCOORDP2UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glTexCoordP2uiv");
+ glTexCoordP3ui = (PFNGLTEXCOORDP3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glTexCoordP3ui");
+ glTexCoordP3uiv = (PFNGLTEXCOORDP3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glTexCoordP3uiv");
+ glTexCoordP4ui = (PFNGLTEXCOORDP4UIPROC)GLH_EXT_GET_PROC_ADDRESS("glTexCoordP4ui");
+ glTexCoordP4uiv = (PFNGLTEXCOORDP4UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glTexCoordP4uiv");
+ glMultiTexCoordP1ui = (PFNGLMULTITEXCOORDP1UIPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoordP1ui");
+ glMultiTexCoordP1uiv = (PFNGLMULTITEXCOORDP1UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoordP1uiv");
+ glMultiTexCoordP2ui = (PFNGLMULTITEXCOORDP2UIPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoordP2ui");
+ glMultiTexCoordP2uiv = (PFNGLMULTITEXCOORDP2UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoordP2uiv");
+ glMultiTexCoordP3ui = (PFNGLMULTITEXCOORDP3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoordP3ui");
+ glMultiTexCoordP3uiv = (PFNGLMULTITEXCOORDP3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoordP3uiv");
+ glMultiTexCoordP4ui = (PFNGLMULTITEXCOORDP4UIPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoordP4ui");
+ glMultiTexCoordP4uiv = (PFNGLMULTITEXCOORDP4UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoordP4uiv");
+ glNormalP3ui = (PFNGLNORMALP3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glNormalP3ui");
+ glNormalP3uiv = (PFNGLNORMALP3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glNormalP3uiv");
+ glColorP3ui = (PFNGLCOLORP3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glColorP3ui");
+ glColorP3uiv = (PFNGLCOLORP3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glColorP3uiv");
+ glColorP4ui = (PFNGLCOLORP4UIPROC)GLH_EXT_GET_PROC_ADDRESS("glColorP4ui");
+ glColorP4uiv = (PFNGLCOLORP4UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glColorP4uiv");
+ glSecondaryColorP3ui = (PFNGLSECONDARYCOLORP3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColorP3ui");
+ glSecondaryColorP3uiv = (PFNGLSECONDARYCOLORP3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColorP3uiv");
+
+ // GL_VERSION_4_0
+ if (mGLVersion < 3.99f)
+ {
+ return;
+ }
+ glMinSampleShading = (PFNGLMINSAMPLESHADINGPROC)GLH_EXT_GET_PROC_ADDRESS("glMinSampleShading");
+ glBlendEquationi = (PFNGLBLENDEQUATIONIPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendEquationi");
+ glBlendEquationSeparatei = (PFNGLBLENDEQUATIONSEPARATEIPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendEquationSeparatei");
+ glBlendFunci = (PFNGLBLENDFUNCIPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendFunci");
+ glBlendFuncSeparatei = (PFNGLBLENDFUNCSEPARATEIPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendFuncSeparatei");
+ glDrawArraysIndirect = (PFNGLDRAWARRAYSINDIRECTPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawArraysIndirect");
+ glDrawElementsIndirect = (PFNGLDRAWELEMENTSINDIRECTPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawElementsIndirect");
+ glUniform1d = (PFNGLUNIFORM1DPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform1d");
+ glUniform2d = (PFNGLUNIFORM2DPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform2d");
+ glUniform3d = (PFNGLUNIFORM3DPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform3d");
+ glUniform4d = (PFNGLUNIFORM4DPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform4d");
+ glUniform1dv = (PFNGLUNIFORM1DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform1dv");
+ glUniform2dv = (PFNGLUNIFORM2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform2dv");
+ glUniform3dv = (PFNGLUNIFORM3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform3dv");
+ glUniform4dv = (PFNGLUNIFORM4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform4dv");
+ glUniformMatrix2dv = (PFNGLUNIFORMMATRIX2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2dv");
+ glUniformMatrix3dv = (PFNGLUNIFORMMATRIX3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3dv");
+ glUniformMatrix4dv = (PFNGLUNIFORMMATRIX4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4dv");
+ glUniformMatrix2x3dv = (PFNGLUNIFORMMATRIX2X3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2x3dv");
+ glUniformMatrix2x4dv = (PFNGLUNIFORMMATRIX2X4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2x4dv");
+ glUniformMatrix3x2dv = (PFNGLUNIFORMMATRIX3X2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3x2dv");
+ glUniformMatrix3x4dv = (PFNGLUNIFORMMATRIX3X4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3x4dv");
+ glUniformMatrix4x2dv = (PFNGLUNIFORMMATRIX4X2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4x2dv");
+ glUniformMatrix4x3dv = (PFNGLUNIFORMMATRIX4X3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4x3dv");
+ glGetUniformdv = (PFNGLGETUNIFORMDVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformdv");
+ glGetSubroutineUniformLocation = (PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC)GLH_EXT_GET_PROC_ADDRESS("glGetSubroutineUniformLocation");
+ glGetSubroutineIndex = (PFNGLGETSUBROUTINEINDEXPROC)GLH_EXT_GET_PROC_ADDRESS("glGetSubroutineIndex");
+ glGetActiveSubroutineUniformiv = (PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveSubroutineUniformiv");
+ glGetActiveSubroutineUniformName = (PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveSubroutineUniformName");
+ glGetActiveSubroutineName = (PFNGLGETACTIVESUBROUTINENAMEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveSubroutineName");
+ glUniformSubroutinesuiv = (PFNGLUNIFORMSUBROUTINESUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformSubroutinesuiv");
+ glGetUniformSubroutineuiv = (PFNGLGETUNIFORMSUBROUTINEUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformSubroutineuiv");
+ glGetProgramStageiv = (PFNGLGETPROGRAMSTAGEIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramStageiv");
+ glPatchParameteri = (PFNGLPATCHPARAMETERIPROC)GLH_EXT_GET_PROC_ADDRESS("glPatchParameteri");
+ glPatchParameterfv = (PFNGLPATCHPARAMETERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glPatchParameterfv");
+ glBindTransformFeedback = (PFNGLBINDTRANSFORMFEEDBACKPROC)GLH_EXT_GET_PROC_ADDRESS("glBindTransformFeedback");
+ glDeleteTransformFeedbacks = (PFNGLDELETETRANSFORMFEEDBACKSPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteTransformFeedbacks");
+ glGenTransformFeedbacks = (PFNGLGENTRANSFORMFEEDBACKSPROC)GLH_EXT_GET_PROC_ADDRESS("glGenTransformFeedbacks");
+ glIsTransformFeedback = (PFNGLISTRANSFORMFEEDBACKPROC)GLH_EXT_GET_PROC_ADDRESS("glIsTransformFeedback");
+ glPauseTransformFeedback = (PFNGLPAUSETRANSFORMFEEDBACKPROC)GLH_EXT_GET_PROC_ADDRESS("glPauseTransformFeedback");
+ glResumeTransformFeedback = (PFNGLRESUMETRANSFORMFEEDBACKPROC)GLH_EXT_GET_PROC_ADDRESS("glResumeTransformFeedback");
+ glDrawTransformFeedback = (PFNGLDRAWTRANSFORMFEEDBACKPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawTransformFeedback");
+ glDrawTransformFeedbackStream = (PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawTransformFeedbackStream");
+ glBeginQueryIndexed = (PFNGLBEGINQUERYINDEXEDPROC)GLH_EXT_GET_PROC_ADDRESS("glBeginQueryIndexed");
+ glEndQueryIndexed = (PFNGLENDQUERYINDEXEDPROC)GLH_EXT_GET_PROC_ADDRESS("glEndQueryIndexed");
+ glGetQueryIndexediv = (PFNGLGETQUERYINDEXEDIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryIndexediv");
+
+ // GL_VERSION_4_1
+ if (mGLVersion < 4.09f)
+ {
+ return;
+ }
+ glReleaseShaderCompiler = (PFNGLRELEASESHADERCOMPILERPROC)GLH_EXT_GET_PROC_ADDRESS("glReleaseShaderCompiler");
+ glShaderBinary = (PFNGLSHADERBINARYPROC)GLH_EXT_GET_PROC_ADDRESS("glShaderBinary");
+ glGetShaderPrecisionFormat = (PFNGLGETSHADERPRECISIONFORMATPROC)GLH_EXT_GET_PROC_ADDRESS("glGetShaderPrecisionFormat");
+ glDepthRangef = (PFNGLDEPTHRANGEFPROC)GLH_EXT_GET_PROC_ADDRESS("glDepthRangef");
+ glClearDepthf = (PFNGLCLEARDEPTHFPROC)GLH_EXT_GET_PROC_ADDRESS("glClearDepthf");
+ glGetProgramBinary = (PFNGLGETPROGRAMBINARYPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramBinary");
+ glProgramBinary = (PFNGLPROGRAMBINARYPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramBinary");
+ glProgramParameteri = (PFNGLPROGRAMPARAMETERIPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramParameteri");
+ glUseProgramStages = (PFNGLUSEPROGRAMSTAGESPROC)GLH_EXT_GET_PROC_ADDRESS("glUseProgramStages");
+ glActiveShaderProgram = (PFNGLACTIVESHADERPROGRAMPROC)GLH_EXT_GET_PROC_ADDRESS("glActiveShaderProgram");
+ glCreateShaderProgramv = (PFNGLCREATESHADERPROGRAMVPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateShaderProgramv");
+ glBindProgramPipeline = (PFNGLBINDPROGRAMPIPELINEPROC)GLH_EXT_GET_PROC_ADDRESS("glBindProgramPipeline");
+ glDeleteProgramPipelines = (PFNGLDELETEPROGRAMPIPELINESPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteProgramPipelines");
+ glGenProgramPipelines = (PFNGLGENPROGRAMPIPELINESPROC)GLH_EXT_GET_PROC_ADDRESS("glGenProgramPipelines");
+ glIsProgramPipeline = (PFNGLISPROGRAMPIPELINEPROC)GLH_EXT_GET_PROC_ADDRESS("glIsProgramPipeline");
+ glGetProgramPipelineiv = (PFNGLGETPROGRAMPIPELINEIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramPipelineiv");
+ glProgramUniform1i = (PFNGLPROGRAMUNIFORM1IPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform1i");
+ glProgramUniform1iv = (PFNGLPROGRAMUNIFORM1IVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform1iv");
+ glProgramUniform1f = (PFNGLPROGRAMUNIFORM1FPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform1f");
+ glProgramUniform1fv = (PFNGLPROGRAMUNIFORM1FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform1fv");
+ glProgramUniform1d = (PFNGLPROGRAMUNIFORM1DPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform1d");
+ glProgramUniform1dv = (PFNGLPROGRAMUNIFORM1DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform1dv");
+ glProgramUniform1ui = (PFNGLPROGRAMUNIFORM1UIPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform1ui");
+ glProgramUniform1uiv = (PFNGLPROGRAMUNIFORM1UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform1uiv");
+ glProgramUniform2i = (PFNGLPROGRAMUNIFORM2IPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform2i");
+ glProgramUniform2iv = (PFNGLPROGRAMUNIFORM2IVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform2iv");
+ glProgramUniform2f = (PFNGLPROGRAMUNIFORM2FPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform2f");
+ glProgramUniform2fv = (PFNGLPROGRAMUNIFORM2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform2fv");
+ glProgramUniform2d = (PFNGLPROGRAMUNIFORM2DPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform2d");
+ glProgramUniform2dv = (PFNGLPROGRAMUNIFORM2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform2dv");
+ glProgramUniform2ui = (PFNGLPROGRAMUNIFORM2UIPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform2ui");
+ glProgramUniform2uiv = (PFNGLPROGRAMUNIFORM2UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform2uiv");
+ glProgramUniform3i = (PFNGLPROGRAMUNIFORM3IPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform3i");
+ glProgramUniform3iv = (PFNGLPROGRAMUNIFORM3IVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform3iv");
+ glProgramUniform3f = (PFNGLPROGRAMUNIFORM3FPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform3f");
+ glProgramUniform3fv = (PFNGLPROGRAMUNIFORM3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform3fv");
+ glProgramUniform3d = (PFNGLPROGRAMUNIFORM3DPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform3d");
+ glProgramUniform3dv = (PFNGLPROGRAMUNIFORM3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform3dv");
+ glProgramUniform3ui = (PFNGLPROGRAMUNIFORM3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform3ui");
+ glProgramUniform3uiv = (PFNGLPROGRAMUNIFORM3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform3uiv");
+ glProgramUniform4i = (PFNGLPROGRAMUNIFORM4IPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform4i");
+ glProgramUniform4iv = (PFNGLPROGRAMUNIFORM4IVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform4iv");
+ glProgramUniform4f = (PFNGLPROGRAMUNIFORM4FPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform4f");
+ glProgramUniform4fv = (PFNGLPROGRAMUNIFORM4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform4fv");
+ glProgramUniform4d = (PFNGLPROGRAMUNIFORM4DPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform4d");
+ glProgramUniform4dv = (PFNGLPROGRAMUNIFORM4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform4dv");
+ glProgramUniform4ui = (PFNGLPROGRAMUNIFORM4UIPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform4ui");
+ glProgramUniform4uiv = (PFNGLPROGRAMUNIFORM4UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform4uiv");
+ glProgramUniformMatrix2fv = (PFNGLPROGRAMUNIFORMMATRIX2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix2fv");
+ glProgramUniformMatrix3fv = (PFNGLPROGRAMUNIFORMMATRIX3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix3fv");
+ glProgramUniformMatrix4fv = (PFNGLPROGRAMUNIFORMMATRIX4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix4fv");
+ glProgramUniformMatrix2dv = (PFNGLPROGRAMUNIFORMMATRIX2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix2dv");
+ glProgramUniformMatrix3dv = (PFNGLPROGRAMUNIFORMMATRIX3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix3dv");
+ glProgramUniformMatrix4dv = (PFNGLPROGRAMUNIFORMMATRIX4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix4dv");
+ glProgramUniformMatrix2x3fv = (PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix2x3fv");
+ glProgramUniformMatrix3x2fv = (PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix3x2fv");
+ glProgramUniformMatrix2x4fv = (PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix2x4fv");
+ glProgramUniformMatrix4x2fv = (PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix4x2fv");
+ glProgramUniformMatrix3x4fv = (PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix3x4fv");
+ glProgramUniformMatrix4x3fv = (PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix4x3fv");
+ glProgramUniformMatrix2x3dv = (PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix2x3dv");
+ glProgramUniformMatrix3x2dv = (PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix3x2dv");
+ glProgramUniformMatrix2x4dv = (PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix2x4dv");
+ glProgramUniformMatrix4x2dv = (PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix4x2dv");
+ glProgramUniformMatrix3x4dv = (PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix3x4dv");
+ glProgramUniformMatrix4x3dv = (PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix4x3dv");
+ glValidateProgramPipeline = (PFNGLVALIDATEPROGRAMPIPELINEPROC)GLH_EXT_GET_PROC_ADDRESS("glValidateProgramPipeline");
+ glGetProgramPipelineInfoLog = (PFNGLGETPROGRAMPIPELINEINFOLOGPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramPipelineInfoLog");
+ glVertexAttribL1d = (PFNGLVERTEXATTRIBL1DPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribL1d");
+ glVertexAttribL2d = (PFNGLVERTEXATTRIBL2DPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribL2d");
+ glVertexAttribL3d = (PFNGLVERTEXATTRIBL3DPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribL3d");
+ glVertexAttribL4d = (PFNGLVERTEXATTRIBL4DPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribL4d");
+ glVertexAttribL1dv = (PFNGLVERTEXATTRIBL1DVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribL1dv");
+ glVertexAttribL2dv = (PFNGLVERTEXATTRIBL2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribL2dv");
+ glVertexAttribL3dv = (PFNGLVERTEXATTRIBL3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribL3dv");
+ glVertexAttribL4dv = (PFNGLVERTEXATTRIBL4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribL4dv");
+ glVertexAttribLPointer = (PFNGLVERTEXATTRIBLPOINTERPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribLPointer");
+ glGetVertexAttribLdv = (PFNGLGETVERTEXATTRIBLDVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribLdv");
+ glViewportArrayv = (PFNGLVIEWPORTARRAYVPROC)GLH_EXT_GET_PROC_ADDRESS("glViewportArrayv");
+ glViewportIndexedf = (PFNGLVIEWPORTINDEXEDFPROC)GLH_EXT_GET_PROC_ADDRESS("glViewportIndexedf");
+ glViewportIndexedfv = (PFNGLVIEWPORTINDEXEDFVPROC)GLH_EXT_GET_PROC_ADDRESS("glViewportIndexedfv");
+ glScissorArrayv = (PFNGLSCISSORARRAYVPROC)GLH_EXT_GET_PROC_ADDRESS("glScissorArrayv");
+ glScissorIndexed = (PFNGLSCISSORINDEXEDPROC)GLH_EXT_GET_PROC_ADDRESS("glScissorIndexed");
+ glScissorIndexedv = (PFNGLSCISSORINDEXEDVPROC)GLH_EXT_GET_PROC_ADDRESS("glScissorIndexedv");
+ glDepthRangeArrayv = (PFNGLDEPTHRANGEARRAYVPROC)GLH_EXT_GET_PROC_ADDRESS("glDepthRangeArrayv");
+ glDepthRangeIndexed = (PFNGLDEPTHRANGEINDEXEDPROC)GLH_EXT_GET_PROC_ADDRESS("glDepthRangeIndexed");
+ glGetFloati_v = (PFNGLGETFLOATI_VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetFloati_v");
+ glGetDoublei_v = (PFNGLGETDOUBLEI_VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetDoublei_v");
+
+ // GL_VERSION_4_2
+ if (mGLVersion < 4.19f)
+ {
+ return;
+ }
+ glDrawArraysInstancedBaseInstance = (PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawArraysInstancedBaseInstance");
+ glDrawElementsInstancedBaseInstance = (PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawElementsInstancedBaseInstance");
+ glDrawElementsInstancedBaseVertexBaseInstance = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawElementsInstancedBaseVertexBaseInstance");
+ glGetInternalformativ = (PFNGLGETINTERNALFORMATIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetInternalformativ");
+ glGetActiveAtomicCounterBufferiv = (PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveAtomicCounterBufferiv");
+ glBindImageTexture = (PFNGLBINDIMAGETEXTUREPROC)GLH_EXT_GET_PROC_ADDRESS("glBindImageTexture");
+ glMemoryBarrier = (PFNGLMEMORYBARRIERPROC)GLH_EXT_GET_PROC_ADDRESS("glMemoryBarrier");
+ glTexStorage1D = (PFNGLTEXSTORAGE1DPROC)GLH_EXT_GET_PROC_ADDRESS("glTexStorage1D");
+ glTexStorage2D = (PFNGLTEXSTORAGE2DPROC)GLH_EXT_GET_PROC_ADDRESS("glTexStorage2D");
+ glTexStorage3D = (PFNGLTEXSTORAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glTexStorage3D");
+ glDrawTransformFeedbackInstanced = (PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawTransformFeedbackInstanced");
+ glDrawTransformFeedbackStreamInstanced = (PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawTransformFeedbackStreamInstanced");
+
+ // GL_VERSION_4_3
+ if (mGLVersion < 4.29f)
+ {
+ return;
+ }
+ glClearBufferData = (PFNGLCLEARBUFFERDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glClearBufferData");
+ glClearBufferSubData = (PFNGLCLEARBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glClearBufferSubData");
+ glDispatchCompute = (PFNGLDISPATCHCOMPUTEPROC)GLH_EXT_GET_PROC_ADDRESS("glDispatchCompute");
+ glDispatchComputeIndirect = (PFNGLDISPATCHCOMPUTEINDIRECTPROC)GLH_EXT_GET_PROC_ADDRESS("glDispatchComputeIndirect");
+ glCopyImageSubData = (PFNGLCOPYIMAGESUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyImageSubData");
+ glFramebufferParameteri = (PFNGLFRAMEBUFFERPARAMETERIPROC)GLH_EXT_GET_PROC_ADDRESS("glFramebufferParameteri");
+ glGetFramebufferParameteriv = (PFNGLGETFRAMEBUFFERPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetFramebufferParameteriv");
+ glGetInternalformati64v = (PFNGLGETINTERNALFORMATI64VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetInternalformati64v");
+ glInvalidateTexSubImage = (PFNGLINVALIDATETEXSUBIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glInvalidateTexSubImage");
+ glInvalidateTexImage = (PFNGLINVALIDATETEXIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glInvalidateTexImage");
+ glInvalidateBufferSubData = (PFNGLINVALIDATEBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glInvalidateBufferSubData");
+ glInvalidateBufferData = (PFNGLINVALIDATEBUFFERDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glInvalidateBufferData");
+ glInvalidateFramebuffer = (PFNGLINVALIDATEFRAMEBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glInvalidateFramebuffer");
+ glInvalidateSubFramebuffer = (PFNGLINVALIDATESUBFRAMEBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glInvalidateSubFramebuffer");
+ glMultiDrawArraysIndirect = (PFNGLMULTIDRAWARRAYSINDIRECTPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiDrawArraysIndirect");
+ glMultiDrawElementsIndirect = (PFNGLMULTIDRAWELEMENTSINDIRECTPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiDrawElementsIndirect");
+ glGetProgramInterfaceiv = (PFNGLGETPROGRAMINTERFACEIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramInterfaceiv");
+ glGetProgramResourceIndex = (PFNGLGETPROGRAMRESOURCEINDEXPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramResourceIndex");
+ glGetProgramResourceName = (PFNGLGETPROGRAMRESOURCENAMEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramResourceName");
+ glGetProgramResourceiv = (PFNGLGETPROGRAMRESOURCEIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramResourceiv");
+ glGetProgramResourceLocation = (PFNGLGETPROGRAMRESOURCELOCATIONPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramResourceLocation");
+ glGetProgramResourceLocationIndex = (PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramResourceLocationIndex");
+ glShaderStorageBlockBinding = (PFNGLSHADERSTORAGEBLOCKBINDINGPROC)GLH_EXT_GET_PROC_ADDRESS("glShaderStorageBlockBinding");
+ glTexBufferRange = (PFNGLTEXBUFFERRANGEPROC)GLH_EXT_GET_PROC_ADDRESS("glTexBufferRange");
+ glTexStorage2DMultisample = (PFNGLTEXSTORAGE2DMULTISAMPLEPROC)GLH_EXT_GET_PROC_ADDRESS("glTexStorage2DMultisample");
+ glTexStorage3DMultisample = (PFNGLTEXSTORAGE3DMULTISAMPLEPROC)GLH_EXT_GET_PROC_ADDRESS("glTexStorage3DMultisample");
+ glTextureView = (PFNGLTEXTUREVIEWPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureView");
+ glBindVertexBuffer = (PFNGLBINDVERTEXBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glBindVertexBuffer");
+ glVertexAttribFormat = (PFNGLVERTEXATTRIBFORMATPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribFormat");
+ glVertexAttribIFormat = (PFNGLVERTEXATTRIBIFORMATPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribIFormat");
+ glVertexAttribLFormat = (PFNGLVERTEXATTRIBLFORMATPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribLFormat");
+ glVertexAttribBinding = (PFNGLVERTEXATTRIBBINDINGPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribBinding");
+ glVertexBindingDivisor = (PFNGLVERTEXBINDINGDIVISORPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexBindingDivisor");
+ glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC)GLH_EXT_GET_PROC_ADDRESS("glDebugMessageControl");
+ glDebugMessageInsert = (PFNGLDEBUGMESSAGEINSERTPROC)GLH_EXT_GET_PROC_ADDRESS("glDebugMessageInsert");
+ glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC)GLH_EXT_GET_PROC_ADDRESS("glDebugMessageCallback");
+ glGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGPROC)GLH_EXT_GET_PROC_ADDRESS("glGetDebugMessageLog");
+ glPushDebugGroup = (PFNGLPUSHDEBUGGROUPPROC)GLH_EXT_GET_PROC_ADDRESS("glPushDebugGroup");
+ glPopDebugGroup = (PFNGLPOPDEBUGGROUPPROC)GLH_EXT_GET_PROC_ADDRESS("glPopDebugGroup");
+ glObjectLabel = (PFNGLOBJECTLABELPROC)GLH_EXT_GET_PROC_ADDRESS("glObjectLabel");
+ glGetObjectLabel = (PFNGLGETOBJECTLABELPROC)GLH_EXT_GET_PROC_ADDRESS("glGetObjectLabel");
+ glObjectPtrLabel = (PFNGLOBJECTPTRLABELPROC)GLH_EXT_GET_PROC_ADDRESS("glObjectPtrLabel");
+ glGetObjectPtrLabel = (PFNGLGETOBJECTPTRLABELPROC)GLH_EXT_GET_PROC_ADDRESS("glGetObjectPtrLabel");
+
+ // GL_VERSION_4_4
+ if (mGLVersion < 4.39f)
+ {
+ return;
+ }
+ glBufferStorage = (PFNGLBUFFERSTORAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glBufferStorage");
+ glClearTexImage = (PFNGLCLEARTEXIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glClearTexImage");
+ glClearTexSubImage = (PFNGLCLEARTEXSUBIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glClearTexSubImage");
+ glBindBuffersBase = (PFNGLBINDBUFFERSBASEPROC)GLH_EXT_GET_PROC_ADDRESS("glBindBuffersBase");
+ glBindBuffersRange = (PFNGLBINDBUFFERSRANGEPROC)GLH_EXT_GET_PROC_ADDRESS("glBindBuffersRange");
+ glBindTextures = (PFNGLBINDTEXTURESPROC)GLH_EXT_GET_PROC_ADDRESS("glBindTextures");
+ glBindSamplers = (PFNGLBINDSAMPLERSPROC)GLH_EXT_GET_PROC_ADDRESS("glBindSamplers");
+ glBindImageTextures = (PFNGLBINDIMAGETEXTURESPROC)GLH_EXT_GET_PROC_ADDRESS("glBindImageTextures");
+ glBindVertexBuffers = (PFNGLBINDVERTEXBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glBindVertexBuffers");
+
+ // GL_VERSION_4_5
+ if (mGLVersion < 4.49f)
+ {
+ return;
+ }
+ glClipControl = (PFNGLCLIPCONTROLPROC)GLH_EXT_GET_PROC_ADDRESS("glClipControl");
+ glCreateTransformFeedbacks = (PFNGLCREATETRANSFORMFEEDBACKSPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateTransformFeedbacks");
+ glTransformFeedbackBufferBase = (PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC)GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackBufferBase");
+ glTransformFeedbackBufferRange = (PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC)GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackBufferRange");
+ glGetTransformFeedbackiv = (PFNGLGETTRANSFORMFEEDBACKIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTransformFeedbackiv");
+ glGetTransformFeedbacki_v = (PFNGLGETTRANSFORMFEEDBACKI_VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTransformFeedbacki_v");
+ glGetTransformFeedbacki64_v = (PFNGLGETTRANSFORMFEEDBACKI64_VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTransformFeedbacki64_v");
+ glCreateBuffers = (PFNGLCREATEBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateBuffers");
+ glNamedBufferStorage = (PFNGLNAMEDBUFFERSTORAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedBufferStorage");
+ glNamedBufferData = (PFNGLNAMEDBUFFERDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedBufferData");
+ glNamedBufferSubData = (PFNGLNAMEDBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedBufferSubData");
+ glCopyNamedBufferSubData = (PFNGLCOPYNAMEDBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyNamedBufferSubData");
+ glClearNamedBufferData = (PFNGLCLEARNAMEDBUFFERDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glClearNamedBufferData");
+ glClearNamedBufferSubData = (PFNGLCLEARNAMEDBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glClearNamedBufferSubData");
+ glMapNamedBuffer = (PFNGLMAPNAMEDBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glMapNamedBuffer");
+ glMapNamedBufferRange = (PFNGLMAPNAMEDBUFFERRANGEPROC)GLH_EXT_GET_PROC_ADDRESS("glMapNamedBufferRange");
+ glUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glUnmapNamedBuffer");
+ glFlushMappedNamedBufferRange = (PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC)GLH_EXT_GET_PROC_ADDRESS("glFlushMappedNamedBufferRange");
+ glGetNamedBufferParameteriv = (PFNGLGETNAMEDBUFFERPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetNamedBufferParameteriv");
+ glGetNamedBufferParameteri64v = (PFNGLGETNAMEDBUFFERPARAMETERI64VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetNamedBufferParameteri64v");
+ glGetNamedBufferPointerv = (PFNGLGETNAMEDBUFFERPOINTERVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetNamedBufferPointerv");
+ glGetNamedBufferSubData = (PFNGLGETNAMEDBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glGetNamedBufferSubData");
+ glCreateFramebuffers = (PFNGLCREATEFRAMEBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateFramebuffers");
+ glNamedFramebufferRenderbuffer = (PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedFramebufferRenderbuffer");
+ glNamedFramebufferParameteri = (PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedFramebufferParameteri");
+ glNamedFramebufferTexture = (PFNGLNAMEDFRAMEBUFFERTEXTUREPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedFramebufferTexture");
+ glNamedFramebufferTextureLayer = (PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedFramebufferTextureLayer");
+ glNamedFramebufferDrawBuffer = (PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedFramebufferDrawBuffer");
+ glNamedFramebufferDrawBuffers = (PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedFramebufferDrawBuffers");
+ glNamedFramebufferReadBuffer = (PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedFramebufferReadBuffer");
+ glInvalidateNamedFramebufferData = (PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glInvalidateNamedFramebufferData");
+ glInvalidateNamedFramebufferSubData = (PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glInvalidateNamedFramebufferSubData");
+ glClearNamedFramebufferiv = (PFNGLCLEARNAMEDFRAMEBUFFERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glClearNamedFramebufferiv");
+ glClearNamedFramebufferuiv = (PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glClearNamedFramebufferuiv");
+ glClearNamedFramebufferfv = (PFNGLCLEARNAMEDFRAMEBUFFERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glClearNamedFramebufferfv");
+ glClearNamedFramebufferfi = (PFNGLCLEARNAMEDFRAMEBUFFERFIPROC)GLH_EXT_GET_PROC_ADDRESS("glClearNamedFramebufferfi");
+ glBlitNamedFramebuffer = (PFNGLBLITNAMEDFRAMEBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glBlitNamedFramebuffer");
+ glCheckNamedFramebufferStatus = (PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC)GLH_EXT_GET_PROC_ADDRESS("glCheckNamedFramebufferStatus");
+ glGetNamedFramebufferParameteriv = (PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetNamedFramebufferParameteriv");
+ glGetNamedFramebufferAttachmentParameteriv = (PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetNamedFramebufferAttachmentParameteriv");
+ glCreateRenderbuffers = (PFNGLCREATERENDERBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateRenderbuffers");
+ glNamedRenderbufferStorage = (PFNGLNAMEDRENDERBUFFERSTORAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedRenderbufferStorage");
+ glNamedRenderbufferStorageMultisample = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedRenderbufferStorageMultisample");
+ glGetNamedRenderbufferParameteriv = (PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetNamedRenderbufferParameteriv");
+ glCreateTextures = (PFNGLCREATETEXTURESPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateTextures");
+ glTextureBuffer = (PFNGLTEXTUREBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureBuffer");
+ glTextureBufferRange = (PFNGLTEXTUREBUFFERRANGEPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureBufferRange");
+ glTextureStorage1D = (PFNGLTEXTURESTORAGE1DPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureStorage1D");
+ glTextureStorage2D = (PFNGLTEXTURESTORAGE2DPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureStorage2D");
+ glTextureStorage3D = (PFNGLTEXTURESTORAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureStorage3D");
+ glTextureStorage2DMultisample = (PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureStorage2DMultisample");
+ glTextureStorage3DMultisample = (PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureStorage3DMultisample");
+ glTextureSubImage1D = (PFNGLTEXTURESUBIMAGE1DPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureSubImage1D");
+ glTextureSubImage2D = (PFNGLTEXTURESUBIMAGE2DPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureSubImage2D");
+ glTextureSubImage3D = (PFNGLTEXTURESUBIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureSubImage3D");
+ glCompressedTextureSubImage1D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTextureSubImage1D");
+ glCompressedTextureSubImage2D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTextureSubImage2D");
+ glCompressedTextureSubImage3D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTextureSubImage3D");
+ glCopyTextureSubImage1D = (PFNGLCOPYTEXTURESUBIMAGE1DPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyTextureSubImage1D");
+ glCopyTextureSubImage2D = (PFNGLCOPYTEXTURESUBIMAGE2DPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyTextureSubImage2D");
+ glCopyTextureSubImage3D = (PFNGLCOPYTEXTURESUBIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyTextureSubImage3D");
+ glTextureParameterf = (PFNGLTEXTUREPARAMETERFPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureParameterf");
+ glTextureParameterfv = (PFNGLTEXTUREPARAMETERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureParameterfv");
+ glTextureParameteri = (PFNGLTEXTUREPARAMETERIPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureParameteri");
+ glTextureParameterIiv = (PFNGLTEXTUREPARAMETERIIVPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureParameterIiv");
+ glTextureParameterIuiv = (PFNGLTEXTUREPARAMETERIUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureParameterIuiv");
+ glTextureParameteriv = (PFNGLTEXTUREPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureParameteriv");
+ glGenerateTextureMipmap = (PFNGLGENERATETEXTUREMIPMAPPROC)GLH_EXT_GET_PROC_ADDRESS("glGenerateTextureMipmap");
+ glBindTextureUnit = (PFNGLBINDTEXTUREUNITPROC)GLH_EXT_GET_PROC_ADDRESS("glBindTextureUnit");
+ glGetTextureImage = (PFNGLGETTEXTUREIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTextureImage");
+ glGetCompressedTextureImage = (PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetCompressedTextureImage");
+ glGetTextureLevelParameterfv = (PFNGLGETTEXTURELEVELPARAMETERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTextureLevelParameterfv");
+ glGetTextureLevelParameteriv = (PFNGLGETTEXTURELEVELPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTextureLevelParameteriv");
+ glGetTextureParameterfv = (PFNGLGETTEXTUREPARAMETERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTextureParameterfv");
+ glGetTextureParameterIiv = (PFNGLGETTEXTUREPARAMETERIIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTextureParameterIiv");
+ glGetTextureParameterIuiv = (PFNGLGETTEXTUREPARAMETERIUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTextureParameterIuiv");
+ glGetTextureParameteriv = (PFNGLGETTEXTUREPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTextureParameteriv");
+ glCreateVertexArrays = (PFNGLCREATEVERTEXARRAYSPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateVertexArrays");
+ glDisableVertexArrayAttrib = (PFNGLDISABLEVERTEXARRAYATTRIBPROC)GLH_EXT_GET_PROC_ADDRESS("glDisableVertexArrayAttrib");
+ glEnableVertexArrayAttrib = (PFNGLENABLEVERTEXARRAYATTRIBPROC)GLH_EXT_GET_PROC_ADDRESS("glEnableVertexArrayAttrib");
+ glVertexArrayElementBuffer = (PFNGLVERTEXARRAYELEMENTBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexArrayElementBuffer");
+ glVertexArrayVertexBuffer = (PFNGLVERTEXARRAYVERTEXBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexArrayVertexBuffer");
+ glVertexArrayVertexBuffers = (PFNGLVERTEXARRAYVERTEXBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexArrayVertexBuffers");
+ glVertexArrayAttribBinding = (PFNGLVERTEXARRAYATTRIBBINDINGPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexArrayAttribBinding");
+ glVertexArrayAttribFormat = (PFNGLVERTEXARRAYATTRIBFORMATPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexArrayAttribFormat");
+ glVertexArrayAttribIFormat = (PFNGLVERTEXARRAYATTRIBIFORMATPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexArrayAttribIFormat");
+ glVertexArrayAttribLFormat = (PFNGLVERTEXARRAYATTRIBLFORMATPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexArrayAttribLFormat");
+ glVertexArrayBindingDivisor = (PFNGLVERTEXARRAYBINDINGDIVISORPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexArrayBindingDivisor");
+ glGetVertexArrayiv = (PFNGLGETVERTEXARRAYIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexArrayiv");
+ glGetVertexArrayIndexediv = (PFNGLGETVERTEXARRAYINDEXEDIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexArrayIndexediv");
+ glGetVertexArrayIndexed64iv = (PFNGLGETVERTEXARRAYINDEXED64IVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexArrayIndexed64iv");
+ glCreateSamplers = (PFNGLCREATESAMPLERSPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateSamplers");
+ glCreateProgramPipelines = (PFNGLCREATEPROGRAMPIPELINESPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateProgramPipelines");
+ glCreateQueries = (PFNGLCREATEQUERIESPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateQueries");
+ glGetQueryBufferObjecti64v = (PFNGLGETQUERYBUFFEROBJECTI64VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryBufferObjecti64v");
+ glGetQueryBufferObjectiv = (PFNGLGETQUERYBUFFEROBJECTIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryBufferObjectiv");
+ glGetQueryBufferObjectui64v = (PFNGLGETQUERYBUFFEROBJECTUI64VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryBufferObjectui64v");
+ glGetQueryBufferObjectuiv = (PFNGLGETQUERYBUFFEROBJECTUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryBufferObjectuiv");
+ glMemoryBarrierByRegion = (PFNGLMEMORYBARRIERBYREGIONPROC)GLH_EXT_GET_PROC_ADDRESS("glMemoryBarrierByRegion");
+ glGetTextureSubImage = (PFNGLGETTEXTURESUBIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTextureSubImage");
+ glGetCompressedTextureSubImage = (PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetCompressedTextureSubImage");
+ glGetGraphicsResetStatus = (PFNGLGETGRAPHICSRESETSTATUSPROC)GLH_EXT_GET_PROC_ADDRESS("glGetGraphicsResetStatus");
+ glGetnCompressedTexImage = (PFNGLGETNCOMPRESSEDTEXIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnCompressedTexImage");
+ glGetnTexImage = (PFNGLGETNTEXIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnTexImage");
+ glGetnUniformdv = (PFNGLGETNUNIFORMDVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnUniformdv");
+ glGetnUniformfv = (PFNGLGETNUNIFORMFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnUniformfv");
+ glGetnUniformiv = (PFNGLGETNUNIFORMIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnUniformiv");
+ glGetnUniformuiv = (PFNGLGETNUNIFORMUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnUniformuiv");
+ glReadnPixels = (PFNGLREADNPIXELSPROC)GLH_EXT_GET_PROC_ADDRESS("glReadnPixels");
+ glGetnMapdv = (PFNGLGETNMAPDVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnMapdv");
+ glGetnMapfv = (PFNGLGETNMAPFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnMapfv");
+ glGetnMapiv = (PFNGLGETNMAPIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnMapiv");
+ glGetnPixelMapfv = (PFNGLGETNPIXELMAPFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnPixelMapfv");
+ glGetnPixelMapuiv = (PFNGLGETNPIXELMAPUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnPixelMapuiv");
+ glGetnPixelMapusv = (PFNGLGETNPIXELMAPUSVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnPixelMapusv");
+ glGetnPolygonStipple = (PFNGLGETNPOLYGONSTIPPLEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnPolygonStipple");
+ glGetnColorTable = (PFNGLGETNCOLORTABLEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnColorTable");
+ glGetnConvolutionFilter = (PFNGLGETNCONVOLUTIONFILTERPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnConvolutionFilter");
+ glGetnSeparableFilter = (PFNGLGETNSEPARABLEFILTERPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnSeparableFilter");
+ glGetnHistogram = (PFNGLGETNHISTOGRAMPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnHistogram");
+ glGetnMinmax = (PFNGLGETNMINMAXPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnMinmax");
+ glTextureBarrier = (PFNGLTEXTUREBARRIERPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureBarrier");
+
+ // GL_VERSION_4_6
+ if (mGLVersion < 4.59f)
+ {
+ return;
+ }
+ glSpecializeShader = (PFNGLSPECIALIZESHADERPROC)GLH_EXT_GET_PROC_ADDRESS("glSpecializeShader");
+ glMultiDrawArraysIndirectCount = (PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiDrawArraysIndirectCount");
+ glMultiDrawElementsIndirectCount = (PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiDrawElementsIndirectCount");
+ glPolygonOffsetClamp = (PFNGLPOLYGONOFFSETCLAMPPROC)GLH_EXT_GET_PROC_ADDRESS("glPolygonOffsetClamp");
+
#endif
-
- mInited = TRUE;
}
void rotate_quat(LLQuaternion& rotation)
@@ -1492,7 +2286,7 @@ void do_assert_glerror()
GLenum error;
error = glGetError();
BOOL quit = FALSE;
- while (LL_UNLIKELY(error))
+ if (LL_UNLIKELY(error))
{
quit = TRUE;
GLubyte const * gl_error_msg = gluErrorString(error);
@@ -1517,7 +2311,6 @@ void do_assert_glerror()
gFailLog << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << std::endl;
}
}
- error = glGetError();
}
if (quit)
@@ -1582,8 +2375,8 @@ void LLGLState::initClass()
// sStateMap[GL_TEXTURE_2D] = GL_TRUE;
//make sure multisample defaults to disabled
- sStateMap[GL_MULTISAMPLE_ARB] = GL_FALSE;
- glDisable(GL_MULTISAMPLE_ARB);
+ sStateMap[GL_MULTISAMPLE] = GL_FALSE;
+ glDisable(GL_MULTISAMPLE);
}
//static
@@ -1604,7 +2397,7 @@ void LLGLState::resetTextureStates()
for (S32 j = maxTextureUnits-1; j >=0; j--)
{
gGL.getTexUnit(j)->activate();
- glClientActiveTextureARB(GL_TEXTURE0_ARB+j);
+ glClientActiveTexture(GL_TEXTURE0+j);
j == 0 ? gGL.getTexUnit(j)->enable(LLTexUnit::TT_TEXTURE) : gGL.getTexUnit(j)->disable();
}
}
@@ -1619,240 +2412,40 @@ void LLGLState::dumpStates()
}
}
-void LLGLState::checkStates(const std::string& msg)
+void LLGLState::checkStates(GLboolean writeAlpha)
{
if (!gDebugGL)
{
return;
}
- stop_glerror();
-
GLint src;
GLint dst;
glGetIntegerv(GL_BLEND_SRC, &src);
glGetIntegerv(GL_BLEND_DST, &dst);
-
- stop_glerror();
-
- BOOL error = FALSE;
-
- if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA)
- {
- if (gDebugSession)
- {
- gFailLog << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << std::endl;
- error = TRUE;
- }
- else
- {
- LL_GL_ERRS << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << LL_ENDL;
- }
- }
+ llassert_always(src == GL_SRC_ALPHA);
+ llassert_always(dst == GL_ONE_MINUS_SRC_ALPHA);
+
+ // disable for now until usage is consistent
+ //GLboolean colorMask[4];
+ //glGetBooleanv(GL_COLOR_WRITEMASK, colorMask);
+ //llassert_always(colorMask[0]);
+ //llassert_always(colorMask[1]);
+ //llassert_always(colorMask[2]);
+ // llassert_always(colorMask[3] == writeAlpha);
for (boost::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
iter != sStateMap.end(); ++iter)
{
LLGLenum state = iter->first;
LLGLboolean cur_state = iter->second;
- stop_glerror();
LLGLboolean gl_state = glIsEnabled(state);
- stop_glerror();
if(cur_state != gl_state)
{
dumpStates();
- if (gDebugSession)
- {
- gFailLog << llformat("LLGLState error. State: 0x%04x",state) << std::endl;
- error = TRUE;
- }
- else
- {
- LL_GL_ERRS << llformat("LLGLState error. State: 0x%04x",state) << LL_ENDL;
- }
+ LL_GL_ERRS << llformat("LLGLState error. State: 0x%04x",state) << LL_ENDL;
}
}
-
- if (error)
- {
- ll_fail("LLGLState::checkStates failed.");
- }
- stop_glerror();
-}
-
-void LLGLState::checkTextureChannels(const std::string& msg)
-{
-#if 0
- if (!gDebugGL)
- {
- return;
- }
- stop_glerror();
-
- GLint activeTexture;
- glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &activeTexture);
- stop_glerror();
-
- BOOL error = FALSE;
-
- if (activeTexture == GL_TEXTURE0_ARB)
- {
- GLint tex_env_mode = 0;
-
- glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env_mode);
- stop_glerror();
-
- if (tex_env_mode != GL_MODULATE)
- {
- error = TRUE;
- LL_WARNS("RenderState") << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << std::dec << LL_ENDL;
- if (gDebugSession)
- {
- gFailLog << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << std::dec << std::endl;
- }
- }
- }
-
- static const char* label[] =
- {
- "GL_TEXTURE_2D",
- "GL_TEXTURE_COORD_ARRAY",
- "GL_TEXTURE_1D",
- "GL_TEXTURE_CUBE_MAP_ARB",
- "GL_TEXTURE_GEN_S",
- "GL_TEXTURE_GEN_T",
- "GL_TEXTURE_GEN_Q",
- "GL_TEXTURE_GEN_R",
- "GL_TEXTURE_RECTANGLE_ARB",
- "GL_TEXTURE_2D_MULTISAMPLE"
- };
-
- static GLint value[] =
- {
- GL_TEXTURE_2D,
- GL_TEXTURE_COORD_ARRAY,
- GL_TEXTURE_1D,
- GL_TEXTURE_CUBE_MAP_ARB,
- GL_TEXTURE_GEN_S,
- GL_TEXTURE_GEN_T,
- GL_TEXTURE_GEN_Q,
- GL_TEXTURE_GEN_R,
- GL_TEXTURE_RECTANGLE_ARB,
- GL_TEXTURE_2D_MULTISAMPLE
- };
-
- GLint stackDepth = 0;
-
- glh::matrix4f mat;
- glh::matrix4f identity;
- identity.identity();
-
- for (GLint i = 1; i < gGLManager.mNumTextureUnits; i++)
- {
- gGL.getTexUnit(i)->activate();
-
- if (i < gGLManager.mNumTextureUnits)
- {
- glClientActiveTextureARB(GL_TEXTURE0_ARB+i);
- stop_glerror();
- glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &stackDepth);
- stop_glerror();
-
- if (stackDepth != 1)
- {
- error = TRUE;
- LL_WARNS("RenderState") << "Texture matrix stack corrupted." << LL_ENDL;
-
- if (gDebugSession)
- {
- gFailLog << "Texture matrix stack corrupted." << std::endl;
- }
- }
-
- glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) mat.m);
- stop_glerror();
-
- if (mat != identity)
- {
- error = TRUE;
- LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL;
- if (gDebugSession)
- {
- gFailLog << "Texture matrix in channel " << i << " corrupt." << std::endl;
- }
- }
-
- for (S32 j = (i == 0 ? 1 : 0);
- j < 9; j++)
- {
- if (j == 8 && !gGLManager.mHasTextureRectangle ||
- j == 9 && !gGLManager.mHasTextureMultisample)
- {
- continue;
- }
-
- if (glIsEnabled(value[j]))
- {
- error = TRUE;
- LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL;
- if (gDebugSession)
- {
- gFailLog << "Texture channel " << i << " still has " << label[j] << " enabled." << std::endl;
- }
- }
- stop_glerror();
- }
-
- glGetFloatv(GL_TEXTURE_MATRIX, mat.m);
- stop_glerror();
-
- if (mat != identity)
- {
- error = TRUE;
- LL_WARNS("RenderState") << "Texture matrix " << i << " is not identity." << LL_ENDL;
- if (gDebugSession)
- {
- gFailLog << "Texture matrix " << i << " is not identity." << std::endl;
- }
- }
- }
-
- {
- GLint tex = 0;
- stop_glerror();
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex);
- stop_glerror();
-
- if (tex != 0)
- {
- error = TRUE;
- LL_WARNS("RenderState") << "Texture channel " << i << " still has texture " << tex << " bound." << LL_ENDL;
-
- if (gDebugSession)
- {
- gFailLog << "Texture channel " << i << " still has texture " << tex << " bound." << std::endl;
- }
- }
- }
- }
-
- stop_glerror();
- gGL.getTexUnit(0)->activate();
- glClientActiveTextureARB(GL_TEXTURE0_ARB);
- stop_glerror();
-
- if (error)
- {
- if (gDebugSession)
- {
- ll_fail("LLGLState::checkTextureChannels failed.");
- }
- else
- {
- LL_GL_ERRS << "GL texture state corruption detected. " << msg << LL_ENDL;
- }
- }
-#endif
}
///////////////////////////////////////////////////////////////////////
@@ -1861,32 +2454,11 @@ LLGLState::LLGLState(LLGLenum state, S32 enabled) :
mState(state), mWasEnabled(FALSE), mIsEnabled(FALSE)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
- switch (state)
- {
- case GL_ALPHA_TEST:
- case GL_NORMALIZE:
- case GL_TEXTURE_GEN_R:
- case GL_TEXTURE_GEN_S:
- case GL_TEXTURE_GEN_T:
- case GL_TEXTURE_GEN_Q:
- case GL_LIGHTING:
- case GL_COLOR_MATERIAL:
- case GL_FOG:
- case GL_LINE_STIPPLE:
- case GL_POLYGON_STIPPLE:
- mState = 0;
- break;
- }
-
- stop_glerror();
if (mState)
{
mWasEnabled = sStateMap[state];
- // we can't actually assert on this as queued changes to state are not reflected by glIsEnabled
- //llassert(mWasEnabled == glIsEnabled(state));
setEnabled(enabled);
- stop_glerror();
}
}
@@ -1918,7 +2490,6 @@ void LLGLState::setEnabled(S32 enabled)
LLGLState::~LLGLState()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
- stop_glerror();
if (mState)
{
if (gDebugGL)
@@ -1951,7 +2522,6 @@ LLGLState::~LLGLState()
}
}
}
- stop_glerror();
}
////////////////////////////////////////////////////////////////////////////////
@@ -2281,36 +2851,29 @@ LLGLSquashToFarClip::~LLGLSquashToFarClip()
LLGLSyncFence::LLGLSyncFence()
{
-#ifdef GL_ARB_sync
mSync = 0;
-#endif
}
LLGLSyncFence::~LLGLSyncFence()
{
-#ifdef GL_ARB_sync
if (mSync)
{
glDeleteSync(mSync);
}
-#endif
}
void LLGLSyncFence::placeFence()
{
-#ifdef GL_ARB_sync
if (mSync)
{
glDeleteSync(mSync);
}
mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
-#endif
}
bool LLGLSyncFence::isCompleted()
{
bool ret = true;
-#ifdef GL_ARB_sync
if (mSync)
{
GLenum status = glClientWaitSync(mSync, 0, 1);
@@ -2319,13 +2882,11 @@ bool LLGLSyncFence::isCompleted()
ret = false;
}
}
-#endif
return ret;
}
void LLGLSyncFence::wait()
{
-#ifdef GL_ARB_sync
if (mSync)
{
while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED)
@@ -2334,12 +2895,10 @@ void LLGLSyncFence::wait()
waits++;
}
}
-#endif
}
LLGLSPipelineSkyBox::LLGLSPipelineSkyBox()
-: mAlphaTest(GL_ALPHA_TEST)
-, mCullFace(GL_CULL_FACE)
+: mCullFace(GL_CULL_FACE)
, mSquashClip()
{
}
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 33cb0706c4..4b0fbc0466 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -76,50 +76,27 @@ public:
BOOL mInited;
BOOL mIsDisabled;
- // Extensions used by everyone
- BOOL mHasMultitexture;
- BOOL mHasATIMemInfo;
- BOOL mHasAMDAssociations;
- BOOL mHasNVXMemInfo;
- S32 mNumTextureUnits;
- BOOL mHasMipMapGeneration;
- BOOL mHasCompressedTextures;
- BOOL mHasFramebufferObject;
+ // OpenGL limits
S32 mMaxSamples;
- BOOL mHasBlendFuncSeparate;
-
- // ARB Extensions
- BOOL mHasVertexBufferObject;
- BOOL mHasVertexArrayObject;
- BOOL mHasSync;
- BOOL mHasMapBufferRange;
- BOOL mHasFlushBufferRange;
- BOOL mHasPBuffer;
- S32 mNumTextureImageUnits;
- BOOL mHasOcclusionQuery;
- BOOL mHasTimerQuery;
- BOOL mHasOcclusionQuery2;
- BOOL mHasPointParameters;
- BOOL mHasDrawBuffers;
- BOOL mHasDepthClamp;
- BOOL mHasTextureRectangle;
- BOOL mHasTextureMultisample;
- BOOL mHasTransformFeedback;
+ S32 mNumTextureImageUnits;
S32 mMaxSampleMaskWords;
S32 mMaxColorTextureSamples;
S32 mMaxDepthTextureSamples;
S32 mMaxIntegerSamples;
-
- // Other extensions.
- BOOL mHasAnisotropic;
- BOOL mHasARBEnvCombine;
- BOOL mHasCubeMap;
- BOOL mHasDebugOutput;
- BOOL mHassRGBTexture;
- BOOL mHassRGBFramebuffer;
- BOOL mHasTexturesRGBDecode;
-
+ S32 mGLMaxVertexRange;
+ S32 mGLMaxIndexRange;
+ S32 mGLMaxTextureSize;
+ F32 mMaxAnisotropy = 0.f;
+
+ // GL 4.x capabilities
+ bool mHasCubeMapArray = false;
+ bool mHasDebugOutput = false;
+ bool mHasTransformFeedback = false;
+ bool mHasAnisotropic = false;
+
// Vendor-specific extensions
+ bool mHasAMDAssociations = false;
+
BOOL mIsAMD;
BOOL mIsNVIDIA;
BOOL mIsIntel;
@@ -132,9 +109,6 @@ public:
// Whether this version of GL is good enough for SL to use
BOOL mHasRequirements;
- // Misc extensions
- BOOL mHasSeparateSpecularColor;
-
S32 mDriverVersionMajor;
S32 mDriverVersionMinor;
S32 mDriverVersionRelease;
@@ -145,9 +119,6 @@ public:
std::string mGLVersionString;
S32 mVRAM; // VRAM in MB
- S32 mGLMaxVertexRange;
- S32 mGLMaxIndexRange;
- S32 mGLMaxTextureSize;
void getPixelFormat(); // Get the best pixel format
@@ -221,13 +192,13 @@ void clear_glerror();
//disable lighting for rendering hud objects
//INCORRECT USAGE
- LLGLEnable lighting(GL_LIGHTING);
+ LLGLEnable blend(GL_BLEND);
renderHUD();
- LLGLDisable lighting(GL_LIGHTING);
+ LLGLDisable blend(GL_BLEND);
//CORRECT USAGE
{
- LLGLEnable lighting(GL_LIGHTING);
+ LLGLEnable blend(GL_BLEND);
renderHUD();
}
@@ -235,7 +206,7 @@ void clear_glerror();
is useful:
{
- LLGLEnable lighting(light_hud ? GL_LIGHTING : 0);
+ LLGLEnable blend(blend_hud ? GL_GL_BLEND: 0);
renderHUD();
}
@@ -260,9 +231,12 @@ public:
static void resetTextureStates();
static void dumpStates();
- static void checkStates(const std::string& msg = "");
- static void checkTextureChannels(const std::string& msg = "");
-
+
+ // make sure GL blend function, GL states, and GL color mask match
+ // what we expect
+ // writeAlpha - whether or not writing to alpha channel is expected
+ static void checkStates(GLboolean writeAlpha = GL_TRUE);
+
protected:
static boost::unordered_map<LLGLenum, LLGLboolean> sStateMap;
@@ -413,9 +387,7 @@ public:
class LLGLSyncFence : public LLGLFence
{
public:
-#ifdef GL_ARB_sync
GLsync mSync;
-#endif
LLGLSyncFence();
virtual ~LLGLSyncFence();
diff --git a/indra/llrender/llglcommonfunc.cpp b/indra/llrender/llglcommonfunc.cpp
index e9ec28927f..04d29b9430 100644
--- a/indra/llrender/llglcommonfunc.cpp
+++ b/indra/llrender/llglcommonfunc.cpp
@@ -31,7 +31,8 @@ namespace LLGLCommonFunc
{
void selected_stencil_test()
{
- glStencilFunc(GL_ALWAYS, 2, 0xffff);
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+ // deprecated
+ //glStencilFunc(GL_ALWAYS, 2, 0xffff);
+ //glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
}
}
diff --git a/indra/llrender/llgldbg.cpp b/indra/llrender/llgldbg.cpp
deleted file mode 100644
index 0f1d4ae742..0000000000
--- a/indra/llrender/llgldbg.cpp
+++ /dev/null
@@ -1,223 +0,0 @@
-/**
- * @file llgldbg.cpp
- * @brief Definitions for OpenGL debugging support
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-// This file sets some global GL parameters, and implements some
-// useful functions for GL operations.
-
-#include "linden_common.h"
-
-#include "llgldbg.h"
-
-#include "llgl.h"
-#include "llglheaders.h"
-
-
-//------------------------------------------------------------------------
-// cmstr()
-//------------------------------------------------------------------------
-const char *cmstr(int i)
-{
- switch( i )
- {
- case GL_EMISSION: return "GL_EMISSION";
- case GL_AMBIENT: return "GL_AMBIENT";
- case GL_DIFFUSE: return "GL_DIFFUSE";
- case GL_SPECULAR: return "GL_SPECULAR";
- case GL_AMBIENT_AND_DIFFUSE: return "GL_AMBIENT_AND_DIFFUSE";
- }
- return "UNKNOWN";
-}
-
-//------------------------------------------------------------------------
-// facestr()
-//------------------------------------------------------------------------
-const char *facestr(int i)
-{
- switch( i )
- {
- case GL_FRONT: return "GL_FRONT";
- case GL_BACK: return "GL_BACK";
- case GL_FRONT_AND_BACK: return "GL_FRONT_AND_BACK";
- }
- return "UNKNOWN";
-}
-
-//------------------------------------------------------------------------
-// boolstr()
-//------------------------------------------------------------------------
-const char *boolstr(int b)
-{
- return b ? "GL_TRUE" : "GL_FALSE";
-}
-
-//------------------------------------------------------------------------
-// fv4()
-//------------------------------------------------------------------------
-const char *fv4(F32 *f)
-{
- static char str[128];
- sprintf(str, "%8.3f %8.3f %8.3f %8.3f", f[0], f[1], f[2], f[3]);
- return str;
-}
-
-//------------------------------------------------------------------------
-// fv3()
-//------------------------------------------------------------------------
-const char *fv3(F32 *f)
-{
- static char str[128]; /* Flawfinder: ignore */
- snprintf(str, sizeof(str), "%8.3f, %8.3f, %8.3f", f[0], f[1], f[2]); /* Flawfinder: ignore */
- return str;
-}
-
-//------------------------------------------------------------------------
-// fv1()
-//------------------------------------------------------------------------
-const char *fv1(F32 *f)
-{
- static char str[128]; /* Flawfinder: ignore */
- snprintf(str, sizeof(str), "%8.3f", f[0]); /* Flawfinder: ignore */
- return str;
-}
-
-//------------------------------------------------------------------------
-// llgl_dump()
-//------------------------------------------------------------------------
-void llgl_dump()
-{
- int i;
- F32 fv[16];
- GLboolean b;
-
- LL_INFOS() << "==========================" << LL_ENDL;
- LL_INFOS() << "OpenGL State" << LL_ENDL;
- LL_INFOS() << "==========================" << LL_ENDL;
-
- LL_INFOS() << "-----------------------------------" << LL_ENDL;
- LL_INFOS() << "Current Values" << LL_ENDL;
- LL_INFOS() << "-----------------------------------" << LL_ENDL;
-
- glGetFloatv(GL_CURRENT_COLOR, fv);
- LL_INFOS() << "GL_CURRENT_COLOR : " << fv4(fv) << LL_ENDL;
-
- glGetFloatv(GL_CURRENT_NORMAL, fv);
- LL_INFOS() << "GL_CURRENT_NORMAL : " << fv3(fv) << LL_ENDL;
-
- LL_INFOS() << "-----------------------------------" << LL_ENDL;
- LL_INFOS() << "Lighting" << LL_ENDL;
- LL_INFOS() << "-----------------------------------" << LL_ENDL;
-
- LL_INFOS() << "GL_LIGHTING : " << boolstr(glIsEnabled(GL_LIGHTING)) << LL_ENDL;
-
- LL_INFOS() << "GL_COLOR_MATERIAL : " << boolstr(glIsEnabled(GL_COLOR_MATERIAL)) << LL_ENDL;
-
- glGetIntegerv(GL_COLOR_MATERIAL_PARAMETER, (GLint*)&i);
- LL_INFOS() << "GL_COLOR_MATERIAL_PARAMETER: " << cmstr(i) << LL_ENDL;
-
- glGetIntegerv(GL_COLOR_MATERIAL_FACE, (GLint*)&i);
- LL_INFOS() << "GL_COLOR_MATERIAL_FACE : " << facestr(i) << LL_ENDL;
-
- fv[0] = fv[1] = fv[2] = fv[3] = 12345.6789f;
- glGetMaterialfv(GL_FRONT, GL_AMBIENT, fv);
- LL_INFOS() << "GL_AMBIENT material : " << fv4(fv) << LL_ENDL;
-
- fv[0] = fv[1] = fv[2] = fv[3] = 12345.6789f;
- glGetMaterialfv(GL_FRONT, GL_DIFFUSE, fv);
- LL_INFOS() << "GL_DIFFUSE material : " << fv4(fv) << LL_ENDL;
-
- fv[0] = fv[1] = fv[2] = fv[3] = 12345.6789f;
- glGetMaterialfv(GL_FRONT, GL_SPECULAR, fv);
- LL_INFOS() << "GL_SPECULAR material : " << fv4(fv) << LL_ENDL;
-
- fv[0] = fv[1] = fv[2] = fv[3] = 12345.6789f;
- glGetMaterialfv(GL_FRONT, GL_EMISSION, fv);
- LL_INFOS() << "GL_EMISSION material : " << fv4(fv) << LL_ENDL;
-
- fv[0] = fv[1] = fv[2] = fv[3] = 12345.6789f;
- glGetMaterialfv(GL_FRONT, GL_SHININESS, fv);
- LL_INFOS() << "GL_SHININESS material : " << fv1(fv) << LL_ENDL;
-
- fv[0] = fv[1] = fv[2] = fv[3] = 12345.6789f;
- glGetFloatv(GL_LIGHT_MODEL_AMBIENT, fv);
- LL_INFOS() << "GL_LIGHT_MODEL_AMBIENT : " << fv4(fv) << LL_ENDL;
-
- glGetBooleanv(GL_LIGHT_MODEL_LOCAL_VIEWER, &b);
- LL_INFOS() << "GL_LIGHT_MODEL_LOCAL_VIEWER: " << boolstr(b) << LL_ENDL;
-
- glGetBooleanv(GL_LIGHT_MODEL_TWO_SIDE, &b);
- LL_INFOS() << "GL_LIGHT_MODEL_TWO_SIDE : " << boolstr(b) << LL_ENDL;
-
- for (int l=0; l<8; l++)
- {
- b = glIsEnabled(GL_LIGHT0+l);
- LL_INFOS() << "GL_LIGHT" << l << " : " << boolstr(b) << LL_ENDL;
-
- if (!b)
- continue;
-
- glGetLightfv(GL_LIGHT0+l, GL_AMBIENT, fv);
- LL_INFOS() << " GL_AMBIENT light : " << fv4(fv) << LL_ENDL;
-
- glGetLightfv(GL_LIGHT0+l, GL_DIFFUSE, fv);
- LL_INFOS() << " GL_DIFFUSE light : " << fv4(fv) << LL_ENDL;
-
- glGetLightfv(GL_LIGHT0+l, GL_SPECULAR, fv);
- LL_INFOS() << " GL_SPECULAR light : " << fv4(fv) << LL_ENDL;
-
- glGetLightfv(GL_LIGHT0+l, GL_POSITION, fv);
- LL_INFOS() << " GL_POSITION light : " << fv4(fv) << LL_ENDL;
-
- glGetLightfv(GL_LIGHT0+l, GL_CONSTANT_ATTENUATION, fv);
- LL_INFOS() << " GL_CONSTANT_ATTENUATION : " << fv1(fv) << LL_ENDL;
-
- glGetLightfv(GL_LIGHT0+l, GL_QUADRATIC_ATTENUATION, fv);
- LL_INFOS() << " GL_QUADRATIC_ATTENUATION : " << fv1(fv) << LL_ENDL;
-
- glGetLightfv(GL_LIGHT0+l, GL_SPOT_DIRECTION, fv);
- LL_INFOS() << " GL_SPOT_DIRECTION : " << fv4(fv) << LL_ENDL;
-
- glGetLightfv(GL_LIGHT0+l, GL_SPOT_EXPONENT, fv);
- LL_INFOS() << " GL_SPOT_EXPONENT : " << fv1(fv) << LL_ENDL;
-
- glGetLightfv(GL_LIGHT0+l, GL_SPOT_CUTOFF, fv);
- LL_INFOS() << " GL_SPOT_CUTOFF : " << fv1(fv) << LL_ENDL;
- }
-
- LL_INFOS() << "-----------------------------------" << LL_ENDL;
- LL_INFOS() << "Pixel Operations" << LL_ENDL;
- LL_INFOS() << "-----------------------------------" << LL_ENDL;
-
- LL_INFOS() << "GL_ALPHA_TEST : " << boolstr(glIsEnabled(GL_ALPHA_TEST)) << LL_ENDL;
- LL_INFOS() << "GL_DEPTH_TEST : " << boolstr(glIsEnabled(GL_DEPTH_TEST)) << LL_ENDL;
-
- glGetBooleanv(GL_DEPTH_WRITEMASK, &b);
- LL_INFOS() << "GL_DEPTH_WRITEMASK : " << boolstr(b) << LL_ENDL;
-
- LL_INFOS() << "GL_BLEND : " << boolstr(glIsEnabled(GL_BLEND)) << LL_ENDL;
- LL_INFOS() << "GL_DITHER : " << boolstr(glIsEnabled(GL_DITHER)) << LL_ENDL;
-}
-
-// End
diff --git a/indra/llrender/llgldbg.h b/indra/llrender/llgldbg.h
deleted file mode 100644
index 963579cb82..0000000000
--- a/indra/llrender/llgldbg.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * @file llgldbg.h
- * @brief Definitions for OpenGL debugging support
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLGLDBG_H
-#define LL_LLGLDBG_H
-
-// Dumps the current OpenGL state to the console.
-void llgl_dump();
-
-
-#endif // LL_LLGLDBG_H
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index e1ecc6a6ca..b80680a3d2 100644
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -41,273 +41,6 @@
# include "GL/glh_extensions.h"
# undef __APPLE__
-#elif LL_LINUX
-//----------------------------------------------------------------------------
-// LL_LINUX
-
-//----------------------------------------------------------------------------
-// Linux, MESA headers, but not necessarily assuming MESA runtime.
-// quotes so we get libraries/.../GL/ version
-#include "GL/gl.h"
-#include "GL/glext.h"
-#include "GL/glu.h"
-
-
-#if LL_LINUX && !LL_MESA_HEADLESS
-// The __APPLE__ kludge is to make glh_extensions.h not symbol-clash horribly
-# define __APPLE__
-# include "GL/glh_extensions.h"
-# undef __APPLE__
-
-#define GLX_GLXEXT_PROTOTYPES 1
-# include "GL/glx.h"
-# include "GL/glxext.h"
-// Use glXGetProcAddressARB instead of glXGetProcAddress - the ARB symbol
-// is considered 'legacy' but works on more machines.
-# define GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddressARB((const GLubyte*)(p))
-#endif // LL_LINUX && !LL_MESA_HEADLESS
-
-#if LL_LINUX && defined(WINGDIAPI)
-// WINGDIAPI gets set if we are using the linux nvidia gl.h header which needs
-// the functions below setting up.
-# define LL_LINUX_NV_GL_HEADERS 1
-#else
-# define LL_LINUX_NV_GL_HEADERS 0
-#endif // LL_LINUX && defined(WINGDIAPI)
-
-
-#if LL_LINUX_NV_GL_HEADERS
-// Missing functions when using nvidia headers:
-extern PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
-extern PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB;
-extern PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements;
-#endif // LL_LINUX_NV_GL_HEADERS
-
-// GL_ARB_vertex_array_object
-extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
-extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
-extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
-extern PFNGLISVERTEXARRAYPROC glIsVertexArray;
-
-// GL_ARB_vertex_buffer_object
-extern PFNGLBINDBUFFERARBPROC glBindBufferARB;
-extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB;
-extern PFNGLGENBUFFERSARBPROC glGenBuffersARB;
-extern PFNGLISBUFFERARBPROC glIsBufferARB;
-extern PFNGLBUFFERDATAARBPROC glBufferDataARB;
-extern PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB;
-extern PFNGLGETBUFFERSUBDATAARBPROC glGetBufferSubDataARB;
-extern PFNGLMAPBUFFERARBPROC glMapBufferARB;
-extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
-extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
-extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
-
-// GL_ARB_sync
-extern PFNGLFENCESYNCPROC glFenceSync;
-extern PFNGLISSYNCPROC glIsSync;
-extern PFNGLDELETESYNCPROC glDeleteSync;
-extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync;
-extern PFNGLWAITSYNCPROC glWaitSync;
-extern PFNGLGETINTEGER64VPROC glGetInteger64v;
-extern PFNGLGETSYNCIVPROC glGetSynciv;
-
-// GL_APPLE_flush_buffer_range
-extern PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE;
-extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE;
-
-// GL_ARB_map_buffer_range
-extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
-extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
-
-// GL_ATI_vertex_array_object
-extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
-extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
-extern PFNGLUPDATEOBJECTBUFFERATIPROC glUpdateObjectBufferATI;
-extern PFNGLGETOBJECTBUFFERFVATIPROC glGetObjectBufferfvATI;
-extern PFNGLGETOBJECTBUFFERIVATIPROC glGetObjectBufferivATI;
-extern PFNGLFREEOBJECTBUFFERATIPROC glFreeObjectBufferATI;
-extern PFNGLARRAYOBJECTATIPROC glArrayObjectATI;
-extern PFNGLVERTEXATTRIBARRAYOBJECTATIPROC glVertexAttribArrayObjectATI;
-extern PFNGLGETARRAYOBJECTFVATIPROC glGetArrayObjectfvATI;
-extern PFNGLGETARRAYOBJECTIVATIPROC glGetArrayObjectivATI;
-extern PFNGLVARIANTARRAYOBJECTATIPROC glVariantObjectArrayATI;
-extern PFNGLGETVARIANTARRAYOBJECTFVATIPROC glGetVariantArrayObjectfvATI;
-extern PFNGLGETVARIANTARRAYOBJECTIVATIPROC glGetVariantArrayObjectivATI;
-
-// GL_ARB_occlusion_query
-extern PFNGLGENQUERIESARBPROC glGenQueriesARB;
-extern PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB;
-extern PFNGLISQUERYARBPROC glIsQueryARB;
-extern PFNGLBEGINQUERYARBPROC glBeginQueryARB;
-extern PFNGLENDQUERYARBPROC glEndQueryARB;
-extern PFNGLGETQUERYIVARBPROC glGetQueryivARB;
-extern PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB;
-extern PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB;
-
-// GL_ARB_timer_query
-extern PFNGLQUERYCOUNTERPROC glQueryCounter;
-extern PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v;
-extern PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v;
-
-// GL_ARB_point_parameters
-extern PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB;
-extern PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB;
-
-// GL_ARB_shader_objects
-extern PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
-extern PFNGLGETHANDLEARBPROC glGetHandleARB;
-extern PFNGLDETACHOBJECTARBPROC glDetachObjectARB;
-extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
-extern PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
-extern PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
-extern PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
-extern PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
-extern PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
-extern PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
-extern PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB;
-extern PFNGLUNIFORM1FARBPROC glUniform1fARB;
-extern PFNGLUNIFORM2FARBPROC glUniform2fARB;
-extern PFNGLUNIFORM3FARBPROC glUniform3fARB;
-extern PFNGLUNIFORM4FARBPROC glUniform4fARB;
-extern PFNGLUNIFORM1IARBPROC glUniform1iARB;
-extern PFNGLUNIFORM2IARBPROC glUniform2iARB;
-extern PFNGLUNIFORM3IARBPROC glUniform3iARB;
-extern PFNGLUNIFORM4IARBPROC glUniform4iARB;
-extern PFNGLUNIFORM1FVARBPROC glUniform1fvARB;
-extern PFNGLUNIFORM2FVARBPROC glUniform2fvARB;
-extern PFNGLUNIFORM3FVARBPROC glUniform3fvARB;
-extern PFNGLUNIFORM4FVARBPROC glUniform4fvARB;
-extern PFNGLUNIFORM1IVARBPROC glUniform1ivARB;
-extern PFNGLUNIFORM2IVARBPROC glUniform2ivARB;
-extern PFNGLUNIFORM3IVARBPROC glUniform3ivARB;
-extern PFNGLUNIFORM4IVARBPROC glUniform4ivARB;
-extern PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB;
-extern PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB;
-extern PFNGLUNIFORMMATRIX3X4FVPROC glUniformMatrix3x4fv;
-extern PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB;
-extern PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB;
-extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
-extern PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
-extern PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB;
-extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
-extern PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB;
-extern PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB;
-extern PFNGLGETUNIFORMIVARBPROC glGetUniformivARB;
-extern PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB;
-
-// GL_ARB_vertex_shader
-extern PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB;
-extern PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB;
-extern PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB;
-extern PFNGLVERTEXATTRIB1FVARBPROC glVertexAttrib1fvARB;
-extern PFNGLVERTEXATTRIB1SARBPROC glVertexAttrib1sARB;
-extern PFNGLVERTEXATTRIB1SVARBPROC glVertexAttrib1svARB;
-extern PFNGLVERTEXATTRIB2DARBPROC glVertexAttrib2dARB;
-extern PFNGLVERTEXATTRIB2DVARBPROC glVertexAttrib2dvARB;
-extern PFNGLVERTEXATTRIB2FARBPROC glVertexAttrib2fARB;
-extern PFNGLVERTEXATTRIB2FVARBPROC glVertexAttrib2fvARB;
-extern PFNGLVERTEXATTRIB2SARBPROC glVertexAttrib2sARB;
-extern PFNGLVERTEXATTRIB2SVARBPROC glVertexAttrib2svARB;
-extern PFNGLVERTEXATTRIB3DARBPROC glVertexAttrib3dARB;
-extern PFNGLVERTEXATTRIB3DVARBPROC glVertexAttrib3dvARB;
-extern PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB;
-extern PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB;
-extern PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB;
-extern PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB;
-extern PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB;
-extern PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB;
-extern PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB;
-extern PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB;
-extern PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB;
-extern PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB;
-extern PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB;
-extern PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB;
-extern PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB;
-extern PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB;
-extern PFNGLVERTEXATTRIB4FARBPROC glVertexAttrib4fARB;
-extern PFNGLVERTEXATTRIB4FVARBPROC glVertexAttrib4fvARB;
-extern PFNGLVERTEXATTRIB4IVARBPROC glVertexAttrib4ivARB;
-extern PFNGLVERTEXATTRIB4SARBPROC glVertexAttrib4sARB;
-extern PFNGLVERTEXATTRIB4SVARBPROC glVertexAttrib4svARB;
-extern PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB;
-extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB;
-extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB;
-extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB;
-extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;
-extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB;
-extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB;
-extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
-extern PFNGLBINDPROGRAMARBPROC glBindProgramARB;
-extern PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
-extern PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
-extern PFNGLPROGRAMENVPARAMETER4DARBPROC glProgramEnvParameter4dARB;
-extern PFNGLPROGRAMENVPARAMETER4DVARBPROC glProgramEnvParameter4dvARB;
-extern PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB;
-extern PFNGLPROGRAMENVPARAMETER4FVARBPROC glProgramEnvParameter4fvARB;
-extern PFNGLPROGRAMLOCALPARAMETER4DARBPROC glProgramLocalParameter4dARB;
-extern PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glProgramLocalParameter4dvARB;
-extern PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB;
-extern PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB;
-extern PFNGLGETPROGRAMENVPARAMETERDVARBPROC glGetProgramEnvParameterdvARB;
-extern PFNGLGETPROGRAMENVPARAMETERFVARBPROC glGetProgramEnvParameterfvARB;
-extern PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glGetProgramLocalParameterdvARB;
-extern PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glGetProgramLocalParameterfvARB;
-extern PFNGLGETPROGRAMIVARBPROC glGetProgramivARB;
-extern PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB;
-extern PFNGLGETVERTEXATTRIBDVARBPROC glGetVertexAttribdvARB;
-extern PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB;
-extern PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB;
-extern PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB;
-extern PFNGLISPROGRAMARBPROC glIsProgramARB;
-extern PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB;
-extern PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB;
-extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB;
-
-extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB;
-extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB;
-
-//GL_EXT_blend_func_separate
-extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT;
-
-//GL_ARB_framebuffer_object
-extern PFNGLISRENDERBUFFERPROC glIsRenderbuffer;
-extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
-extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
-extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
-extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
-extern PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv;
-extern PFNGLISFRAMEBUFFERPROC glIsFramebuffer;
-extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
-extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
-extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
-extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
-extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D;
-extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
-extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D;
-extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
-extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv;
-extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
-extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer;
-extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample;
-extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
-
-//GL_ARB_draw_buffers
-extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;
-
-//GL_ARB_texture_multisample
-extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
-extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
-extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
-extern PFNGLSAMPLEMASKIPROC glSampleMaski;
-
-//transform feedback (4.0 core)
-extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;
-extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;
-extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;
-extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange;
-extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;
-
-
#elif LL_WINDOWS
//----------------------------------------------------------------------------
// LL_WINDOWS
@@ -323,251 +56,774 @@ extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;
#include "GL/glext.h"
#include "GL/glh_extensions.h"
+// WGL_AMD_gpu_association
+extern PFNWGLGETGPUIDSAMDPROC wglGetGPUIDsAMD;
+extern PFNWGLGETGPUINFOAMDPROC wglGetGPUInfoAMD;
+extern PFNWGLGETCONTEXTGPUIDAMDPROC wglGetContextGPUIDAMD;
+extern PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC wglCreateAssociatedContextAMD;
+extern PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC wglCreateAssociatedContextAttribsAMD;
+extern PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC wglDeleteAssociatedContextAMD;
+extern PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC wglMakeAssociatedContextCurrentAMD;
+extern PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC wglGetCurrentAssociatedContextAMD;
+extern PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC wglBlitContextFramebufferAMD;
+
+// WGL_EXT_swap_control
+extern PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
+extern PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT;
+
// WGL_ARB_create_context
extern PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
-extern PFNGLGETSTRINGIPROC glGetStringi;
-
-// GL_ARB_vertex_buffer_object
-extern PFNGLBINDBUFFERARBPROC glBindBufferARB;
-extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB;
-extern PFNGLGENBUFFERSARBPROC glGenBuffersARB;
-extern PFNGLISBUFFERARBPROC glIsBufferARB;
-extern PFNGLBUFFERDATAARBPROC glBufferDataARB;
-extern PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB;
-extern PFNGLGETBUFFERSUBDATAARBPROC glGetBufferSubDataARB;
-extern PFNGLMAPBUFFERARBPROC glMapBufferARB;
-extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
-extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
-extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
-
-// GL_ARB_vertex_array_object
-extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
-extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
-extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
-extern PFNGLISVERTEXARRAYPROC glIsVertexArray;
-
-// GL_ARB_sync
-extern PFNGLFENCESYNCPROC glFenceSync;
-extern PFNGLISSYNCPROC glIsSync;
-extern PFNGLDELETESYNCPROC glDeleteSync;
-extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync;
-extern PFNGLWAITSYNCPROC glWaitSync;
-extern PFNGLGETINTEGER64VPROC glGetInteger64v;
-extern PFNGLGETSYNCIVPROC glGetSynciv;
-
-// GL_APPLE_flush_buffer_range
-extern PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE;
-extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE;
-
-// GL_ARB_map_buffer_range
-extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
-extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
-
-// GL_ATI_vertex_array_object
-extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
-extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
-extern PFNGLUPDATEOBJECTBUFFERATIPROC glUpdateObjectBufferATI;
-extern PFNGLGETOBJECTBUFFERFVATIPROC glGetObjectBufferfvATI;
-extern PFNGLGETOBJECTBUFFERIVATIPROC glGetObjectBufferivATI;
-extern PFNGLFREEOBJECTBUFFERATIPROC glFreeObjectBufferATI;
-extern PFNGLARRAYOBJECTATIPROC glArrayObjectATI;
-extern PFNGLVERTEXATTRIBARRAYOBJECTATIPROC glVertexAttribArrayObjectATI;
-extern PFNGLGETARRAYOBJECTFVATIPROC glGetArrayObjectfvATI;
-extern PFNGLGETARRAYOBJECTIVATIPROC glGetArrayObjectivATI;
-extern PFNGLVARIANTARRAYOBJECTATIPROC glVariantObjectArrayATI;
-extern PFNGLGETVARIANTARRAYOBJECTFVATIPROC glGetVariantArrayObjectfvATI;
-extern PFNGLGETVARIANTARRAYOBJECTIVATIPROC glGetVariantArrayObjectivATI;
-
-extern PFNWGLGETGPUIDSAMDPROC wglGetGPUIDsAMD;
-extern PFNWGLGETGPUINFOAMDPROC wglGetGPUInfoAMD;
-extern PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
-
-// GL_ARB_occlusion_query
-extern PFNGLGENQUERIESARBPROC glGenQueriesARB;
-extern PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB;
-extern PFNGLISQUERYARBPROC glIsQueryARB;
-extern PFNGLBEGINQUERYARBPROC glBeginQueryARB;
-extern PFNGLENDQUERYARBPROC glEndQueryARB;
-extern PFNGLGETQUERYIVARBPROC glGetQueryivARB;
-extern PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB;
-extern PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB;
-
-// GL_ARB_timer_query
-extern PFNGLQUERYCOUNTERPROC glQueryCounter;
-extern PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v;
-extern PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v;
-
-
-// GL_ARB_point_parameters
-extern PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB;
-extern PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB;
-
-// GL_ARB_shader_objects
-extern PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
-extern PFNGLGETHANDLEARBPROC glGetHandleARB;
-extern PFNGLDETACHOBJECTARBPROC glDetachObjectARB;
-extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
-extern PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
-extern PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
-extern PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
-extern PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
-extern PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
-extern PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
-extern PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB;
-extern PFNGLUNIFORM1FARBPROC glUniform1fARB;
-extern PFNGLUNIFORM2FARBPROC glUniform2fARB;
-extern PFNGLUNIFORM3FARBPROC glUniform3fARB;
-extern PFNGLUNIFORM4FARBPROC glUniform4fARB;
-extern PFNGLUNIFORM1IARBPROC glUniform1iARB;
-extern PFNGLUNIFORM2IARBPROC glUniform2iARB;
-extern PFNGLUNIFORM3IARBPROC glUniform3iARB;
-extern PFNGLUNIFORM4IARBPROC glUniform4iARB;
-extern PFNGLUNIFORM1FVARBPROC glUniform1fvARB;
-extern PFNGLUNIFORM2FVARBPROC glUniform2fvARB;
-extern PFNGLUNIFORM3FVARBPROC glUniform3fvARB;
-extern PFNGLUNIFORM4FVARBPROC glUniform4fvARB;
-extern PFNGLUNIFORM1IVARBPROC glUniform1ivARB;
-extern PFNGLUNIFORM2IVARBPROC glUniform2ivARB;
-extern PFNGLUNIFORM3IVARBPROC glUniform3ivARB;
-extern PFNGLUNIFORM4IVARBPROC glUniform4ivARB;
-extern PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB;
-extern PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB;
+
+// GL_VERSION_1_3
+extern PFNGLACTIVETEXTUREPROC glActiveTexture;
+extern PFNGLSAMPLECOVERAGEPROC glSampleCoverage;
+extern PFNGLCOMPRESSEDTEXIMAGE3DPROC glCompressedTexImage3D;
+extern PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D;
+extern PFNGLCOMPRESSEDTEXIMAGE1DPROC glCompressedTexImage1D;
+extern PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glCompressedTexSubImage3D;
+extern PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glCompressedTexSubImage2D;
+extern PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glCompressedTexSubImage1D;
+extern PFNGLGETCOMPRESSEDTEXIMAGEPROC glGetCompressedTexImage;
+extern PFNGLCLIENTACTIVETEXTUREPROC glClientActiveTexture;
+extern PFNGLMULTITEXCOORD1DPROC glMultiTexCoord1d;
+extern PFNGLMULTITEXCOORD1DVPROC glMultiTexCoord1dv;
+extern PFNGLMULTITEXCOORD1FPROC glMultiTexCoord1f;
+extern PFNGLMULTITEXCOORD1FVPROC glMultiTexCoord1fv;
+extern PFNGLMULTITEXCOORD1IPROC glMultiTexCoord1i;
+extern PFNGLMULTITEXCOORD1IVPROC glMultiTexCoord1iv;
+extern PFNGLMULTITEXCOORD1SPROC glMultiTexCoord1s;
+extern PFNGLMULTITEXCOORD1SVPROC glMultiTexCoord1sv;
+extern PFNGLMULTITEXCOORD2DPROC glMultiTexCoord2d;
+extern PFNGLMULTITEXCOORD2DVPROC glMultiTexCoord2dv;
+extern PFNGLMULTITEXCOORD2FPROC glMultiTexCoord2f;
+extern PFNGLMULTITEXCOORD2FVPROC glMultiTexCoord2fv;
+extern PFNGLMULTITEXCOORD2IPROC glMultiTexCoord2i;
+extern PFNGLMULTITEXCOORD2IVPROC glMultiTexCoord2iv;
+extern PFNGLMULTITEXCOORD2SPROC glMultiTexCoord2s;
+extern PFNGLMULTITEXCOORD2SVPROC glMultiTexCoord2sv;
+extern PFNGLMULTITEXCOORD3DPROC glMultiTexCoord3d;
+extern PFNGLMULTITEXCOORD3DVPROC glMultiTexCoord3dv;
+extern PFNGLMULTITEXCOORD3FPROC glMultiTexCoord3f;
+extern PFNGLMULTITEXCOORD3FVPROC glMultiTexCoord3fv;
+extern PFNGLMULTITEXCOORD3IPROC glMultiTexCoord3i;
+extern PFNGLMULTITEXCOORD3IVPROC glMultiTexCoord3iv;
+extern PFNGLMULTITEXCOORD3SPROC glMultiTexCoord3s;
+extern PFNGLMULTITEXCOORD3SVPROC glMultiTexCoord3sv;
+extern PFNGLMULTITEXCOORD4DPROC glMultiTexCoord4d;
+extern PFNGLMULTITEXCOORD4DVPROC glMultiTexCoord4dv;
+extern PFNGLMULTITEXCOORD4FPROC glMultiTexCoord4f;
+extern PFNGLMULTITEXCOORD4FVPROC glMultiTexCoord4fv;
+extern PFNGLMULTITEXCOORD4IPROC glMultiTexCoord4i;
+extern PFNGLMULTITEXCOORD4IVPROC glMultiTexCoord4iv;
+extern PFNGLMULTITEXCOORD4SPROC glMultiTexCoord4s;
+extern PFNGLMULTITEXCOORD4SVPROC glMultiTexCoord4sv;
+extern PFNGLLOADTRANSPOSEMATRIXFPROC glLoadTransposeMatrixf;
+extern PFNGLLOADTRANSPOSEMATRIXDPROC glLoadTransposeMatrixd;
+extern PFNGLMULTTRANSPOSEMATRIXFPROC glMultTransposeMatrixf;
+extern PFNGLMULTTRANSPOSEMATRIXDPROC glMultTransposeMatrixd;
+
+// GL_VERSION_1_4
+extern PFNGLBLENDFUNCSEPARATEPROC glBlendFuncSeparate;
+extern PFNGLMULTIDRAWARRAYSPROC glMultiDrawArrays;
+extern PFNGLMULTIDRAWELEMENTSPROC glMultiDrawElements;
+extern PFNGLPOINTPARAMETERFPROC glPointParameterf;
+extern PFNGLPOINTPARAMETERFVPROC glPointParameterfv;
+extern PFNGLPOINTPARAMETERIPROC glPointParameteri;
+extern PFNGLPOINTPARAMETERIVPROC glPointParameteriv;
+extern PFNGLFOGCOORDFPROC glFogCoordf;
+extern PFNGLFOGCOORDFVPROC glFogCoordfv;
+extern PFNGLFOGCOORDDPROC glFogCoordd;
+extern PFNGLFOGCOORDDVPROC glFogCoorddv;
+extern PFNGLFOGCOORDPOINTERPROC glFogCoordPointer;
+extern PFNGLSECONDARYCOLOR3BPROC glSecondaryColor3b;
+extern PFNGLSECONDARYCOLOR3BVPROC glSecondaryColor3bv;
+extern PFNGLSECONDARYCOLOR3DPROC glSecondaryColor3d;
+extern PFNGLSECONDARYCOLOR3DVPROC glSecondaryColor3dv;
+extern PFNGLSECONDARYCOLOR3FPROC glSecondaryColor3f;
+extern PFNGLSECONDARYCOLOR3FVPROC glSecondaryColor3fv;
+extern PFNGLSECONDARYCOLOR3IPROC glSecondaryColor3i;
+extern PFNGLSECONDARYCOLOR3IVPROC glSecondaryColor3iv;
+extern PFNGLSECONDARYCOLOR3SPROC glSecondaryColor3s;
+extern PFNGLSECONDARYCOLOR3SVPROC glSecondaryColor3sv;
+extern PFNGLSECONDARYCOLOR3UBPROC glSecondaryColor3ub;
+extern PFNGLSECONDARYCOLOR3UBVPROC glSecondaryColor3ubv;
+extern PFNGLSECONDARYCOLOR3UIPROC glSecondaryColor3ui;
+extern PFNGLSECONDARYCOLOR3UIVPROC glSecondaryColor3uiv;
+extern PFNGLSECONDARYCOLOR3USPROC glSecondaryColor3us;
+extern PFNGLSECONDARYCOLOR3USVPROC glSecondaryColor3usv;
+extern PFNGLSECONDARYCOLORPOINTERPROC glSecondaryColorPointer;
+extern PFNGLWINDOWPOS2DPROC glWindowPos2d;
+extern PFNGLWINDOWPOS2DVPROC glWindowPos2dv;
+extern PFNGLWINDOWPOS2FPROC glWindowPos2f;
+extern PFNGLWINDOWPOS2FVPROC glWindowPos2fv;
+extern PFNGLWINDOWPOS2IPROC glWindowPos2i;
+extern PFNGLWINDOWPOS2IVPROC glWindowPos2iv;
+extern PFNGLWINDOWPOS2SPROC glWindowPos2s;
+extern PFNGLWINDOWPOS2SVPROC glWindowPos2sv;
+extern PFNGLWINDOWPOS3DPROC glWindowPos3d;
+extern PFNGLWINDOWPOS3DVPROC glWindowPos3dv;
+extern PFNGLWINDOWPOS3FPROC glWindowPos3f;
+extern PFNGLWINDOWPOS3FVPROC glWindowPos3fv;
+extern PFNGLWINDOWPOS3IPROC glWindowPos3i;
+extern PFNGLWINDOWPOS3IVPROC glWindowPos3iv;
+extern PFNGLWINDOWPOS3SPROC glWindowPos3s;
+extern PFNGLWINDOWPOS3SVPROC glWindowPos3sv;
+
+// GL_VERSION_1_5
+extern PFNGLGENQUERIESPROC glGenQueries;
+extern PFNGLDELETEQUERIESPROC glDeleteQueries;
+extern PFNGLISQUERYPROC glIsQuery;
+extern PFNGLBEGINQUERYPROC glBeginQuery;
+extern PFNGLENDQUERYPROC glEndQuery;
+extern PFNGLGETQUERYIVPROC glGetQueryiv;
+extern PFNGLGETQUERYOBJECTIVPROC glGetQueryObjectiv;
+extern PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv;
+extern PFNGLBINDBUFFERPROC glBindBuffer;
+extern PFNGLDELETEBUFFERSPROC glDeleteBuffers;
+extern PFNGLGENBUFFERSPROC glGenBuffers;
+extern PFNGLISBUFFERPROC glIsBuffer;
+extern PFNGLBUFFERDATAPROC glBufferData;
+extern PFNGLBUFFERSUBDATAPROC glBufferSubData;
+extern PFNGLGETBUFFERSUBDATAPROC glGetBufferSubData;
+extern PFNGLMAPBUFFERPROC glMapBuffer;
+extern PFNGLUNMAPBUFFERPROC glUnmapBuffer;
+extern PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv;
+extern PFNGLGETBUFFERPOINTERVPROC glGetBufferPointerv;
+
+// GL_VERSION_2_0
+extern PFNGLBLENDEQUATIONSEPARATEPROC glBlendEquationSeparate;
+extern PFNGLDRAWBUFFERSPROC glDrawBuffers;
+extern PFNGLSTENCILOPSEPARATEPROC glStencilOpSeparate;
+extern PFNGLSTENCILFUNCSEPARATEPROC glStencilFuncSeparate;
+extern PFNGLSTENCILMASKSEPARATEPROC glStencilMaskSeparate;
+extern PFNGLATTACHSHADERPROC glAttachShader;
+extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
+extern PFNGLCOMPILESHADERPROC glCompileShader;
+extern PFNGLCREATEPROGRAMPROC glCreateProgram;
+extern PFNGLCREATESHADERPROC glCreateShader;
+extern PFNGLDELETEPROGRAMPROC glDeleteProgram;
+extern PFNGLDELETESHADERPROC glDeleteShader;
+extern PFNGLDETACHSHADERPROC glDetachShader;
+extern PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
+extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
+extern PFNGLGETACTIVEATTRIBPROC glGetActiveAttrib;
+extern PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform;
+extern PFNGLGETATTACHEDSHADERSPROC glGetAttachedShaders;
+extern PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
+extern PFNGLGETPROGRAMIVPROC glGetProgramiv;
+extern PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
+extern PFNGLGETSHADERIVPROC glGetShaderiv;
+extern PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
+extern PFNGLGETSHADERSOURCEPROC glGetShaderSource;
+extern PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
+extern PFNGLGETUNIFORMFVPROC glGetUniformfv;
+extern PFNGLGETUNIFORMIVPROC glGetUniformiv;
+extern PFNGLGETVERTEXATTRIBDVPROC glGetVertexAttribdv;
+extern PFNGLGETVERTEXATTRIBFVPROC glGetVertexAttribfv;
+extern PFNGLGETVERTEXATTRIBIVPROC glGetVertexAttribiv;
+extern PFNGLGETVERTEXATTRIBPOINTERVPROC glGetVertexAttribPointerv;
+extern PFNGLISPROGRAMPROC glIsProgram;
+extern PFNGLISSHADERPROC glIsShader;
+extern PFNGLLINKPROGRAMPROC glLinkProgram;
+extern PFNGLSHADERSOURCEPROC glShaderSource;
+extern PFNGLUSEPROGRAMPROC glUseProgram;
+extern PFNGLUNIFORM1FPROC glUniform1f;
+extern PFNGLUNIFORM2FPROC glUniform2f;
+extern PFNGLUNIFORM3FPROC glUniform3f;
+extern PFNGLUNIFORM4FPROC glUniform4f;
+extern PFNGLUNIFORM1IPROC glUniform1i;
+extern PFNGLUNIFORM2IPROC glUniform2i;
+extern PFNGLUNIFORM3IPROC glUniform3i;
+extern PFNGLUNIFORM4IPROC glUniform4i;
+extern PFNGLUNIFORM1FVPROC glUniform1fv;
+extern PFNGLUNIFORM2FVPROC glUniform2fv;
+extern PFNGLUNIFORM3FVPROC glUniform3fv;
+extern PFNGLUNIFORM4FVPROC glUniform4fv;
+extern PFNGLUNIFORM1IVPROC glUniform1iv;
+extern PFNGLUNIFORM2IVPROC glUniform2iv;
+extern PFNGLUNIFORM3IVPROC glUniform3iv;
+extern PFNGLUNIFORM4IVPROC glUniform4iv;
+extern PFNGLUNIFORMMATRIX2FVPROC glUniformMatrix2fv;
+extern PFNGLUNIFORMMATRIX3FVPROC glUniformMatrix3fv;
+extern PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
+extern PFNGLVALIDATEPROGRAMPROC glValidateProgram;
+extern PFNGLVERTEXATTRIB1DPROC glVertexAttrib1d;
+extern PFNGLVERTEXATTRIB1DVPROC glVertexAttrib1dv;
+extern PFNGLVERTEXATTRIB1FPROC glVertexAttrib1f;
+extern PFNGLVERTEXATTRIB1FVPROC glVertexAttrib1fv;
+extern PFNGLVERTEXATTRIB1SPROC glVertexAttrib1s;
+extern PFNGLVERTEXATTRIB1SVPROC glVertexAttrib1sv;
+extern PFNGLVERTEXATTRIB2DPROC glVertexAttrib2d;
+extern PFNGLVERTEXATTRIB2DVPROC glVertexAttrib2dv;
+extern PFNGLVERTEXATTRIB2FPROC glVertexAttrib2f;
+extern PFNGLVERTEXATTRIB2FVPROC glVertexAttrib2fv;
+extern PFNGLVERTEXATTRIB2SPROC glVertexAttrib2s;
+extern PFNGLVERTEXATTRIB2SVPROC glVertexAttrib2sv;
+extern PFNGLVERTEXATTRIB3DPROC glVertexAttrib3d;
+extern PFNGLVERTEXATTRIB3DVPROC glVertexAttrib3dv;
+extern PFNGLVERTEXATTRIB3FPROC glVertexAttrib3f;
+extern PFNGLVERTEXATTRIB3FVPROC glVertexAttrib3fv;
+extern PFNGLVERTEXATTRIB3SPROC glVertexAttrib3s;
+extern PFNGLVERTEXATTRIB3SVPROC glVertexAttrib3sv;
+extern PFNGLVERTEXATTRIB4NBVPROC glVertexAttrib4Nbv;
+extern PFNGLVERTEXATTRIB4NIVPROC glVertexAttrib4Niv;
+extern PFNGLVERTEXATTRIB4NSVPROC glVertexAttrib4Nsv;
+extern PFNGLVERTEXATTRIB4NUBPROC glVertexAttrib4Nub;
+extern PFNGLVERTEXATTRIB4NUBVPROC glVertexAttrib4Nubv;
+extern PFNGLVERTEXATTRIB4NUIVPROC glVertexAttrib4Nuiv;
+extern PFNGLVERTEXATTRIB4NUSVPROC glVertexAttrib4Nusv;
+extern PFNGLVERTEXATTRIB4BVPROC glVertexAttrib4bv;
+extern PFNGLVERTEXATTRIB4DPROC glVertexAttrib4d;
+extern PFNGLVERTEXATTRIB4DVPROC glVertexAttrib4dv;
+extern PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f;
+extern PFNGLVERTEXATTRIB4FVPROC glVertexAttrib4fv;
+extern PFNGLVERTEXATTRIB4IVPROC glVertexAttrib4iv;
+extern PFNGLVERTEXATTRIB4SPROC glVertexAttrib4s;
+extern PFNGLVERTEXATTRIB4SVPROC glVertexAttrib4sv;
+extern PFNGLVERTEXATTRIB4UBVPROC glVertexAttrib4ubv;
+extern PFNGLVERTEXATTRIB4UIVPROC glVertexAttrib4uiv;
+extern PFNGLVERTEXATTRIB4USVPROC glVertexAttrib4usv;
+extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
+
+// GL_VERSION_2_1
+extern PFNGLUNIFORMMATRIX2X3FVPROC glUniformMatrix2x3fv;
+extern PFNGLUNIFORMMATRIX3X2FVPROC glUniformMatrix3x2fv;
+extern PFNGLUNIFORMMATRIX2X4FVPROC glUniformMatrix2x4fv;
+extern PFNGLUNIFORMMATRIX4X2FVPROC glUniformMatrix4x2fv;
extern PFNGLUNIFORMMATRIX3X4FVPROC glUniformMatrix3x4fv;
-extern PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB;
-extern PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB;
-extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
-extern PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
-extern PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB;
-extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
-extern PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB;
-extern PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB;
-extern PFNGLGETUNIFORMIVARBPROC glGetUniformivARB;
-extern PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB;
-
-// GL_ARB_vertex_shader
-extern PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB;
-extern PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB;
-extern PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB;
-extern PFNGLVERTEXATTRIB1FVARBPROC glVertexAttrib1fvARB;
-extern PFNGLVERTEXATTRIB1SARBPROC glVertexAttrib1sARB;
-extern PFNGLVERTEXATTRIB1SVARBPROC glVertexAttrib1svARB;
-extern PFNGLVERTEXATTRIB2DARBPROC glVertexAttrib2dARB;
-extern PFNGLVERTEXATTRIB2DVARBPROC glVertexAttrib2dvARB;
-extern PFNGLVERTEXATTRIB2FARBPROC glVertexAttrib2fARB;
-extern PFNGLVERTEXATTRIB2FVARBPROC glVertexAttrib2fvARB;
-extern PFNGLVERTEXATTRIB2SARBPROC glVertexAttrib2sARB;
-extern PFNGLVERTEXATTRIB2SVARBPROC glVertexAttrib2svARB;
-extern PFNGLVERTEXATTRIB3DARBPROC glVertexAttrib3dARB;
-extern PFNGLVERTEXATTRIB3DVARBPROC glVertexAttrib3dvARB;
-extern PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB;
-extern PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB;
-extern PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB;
-extern PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB;
-extern PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB;
-extern PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB;
-extern PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB;
-extern PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB;
-extern PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB;
-extern PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB;
-extern PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB;
-extern PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB;
-extern PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB;
-extern PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB;
-extern PFNGLVERTEXATTRIB4FARBPROC glVertexAttrib4fARB;
-extern PFNGLVERTEXATTRIB4FVARBPROC glVertexAttrib4fvARB;
-extern PFNGLVERTEXATTRIB4IVARBPROC glVertexAttrib4ivARB;
-extern PFNGLVERTEXATTRIB4SARBPROC glVertexAttrib4sARB;
-extern PFNGLVERTEXATTRIB4SVARBPROC glVertexAttrib4svARB;
-extern PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB;
-extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB;
-extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB;
-extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB;
-extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;
-extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB;
-extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB;
-extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
-extern PFNGLBINDPROGRAMARBPROC glBindProgramARB;
-extern PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
-extern PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
-extern PFNGLPROGRAMENVPARAMETER4DARBPROC glProgramEnvParameter4dARB;
-extern PFNGLPROGRAMENVPARAMETER4DVARBPROC glProgramEnvParameter4dvARB;
-extern PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB;
-extern PFNGLPROGRAMENVPARAMETER4FVARBPROC glProgramEnvParameter4fvARB;
-extern PFNGLPROGRAMLOCALPARAMETER4DARBPROC glProgramLocalParameter4dARB;
-extern PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glProgramLocalParameter4dvARB;
-extern PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB;
-extern PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB;
-extern PFNGLGETPROGRAMENVPARAMETERDVARBPROC glGetProgramEnvParameterdvARB;
-extern PFNGLGETPROGRAMENVPARAMETERFVARBPROC glGetProgramEnvParameterfvARB;
-extern PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glGetProgramLocalParameterdvARB;
-extern PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glGetProgramLocalParameterfvARB;
-extern PFNGLGETPROGRAMIVARBPROC glGetProgramivARB;
-extern PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB;
-extern PFNGLGETVERTEXATTRIBDVARBPROC glGetVertexAttribdvARB;
-extern PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB;
-extern PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB;
-extern PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB;
-extern PFNGLISPROGRAMARBPROC glIsProgramARB;
-extern PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB;
-extern PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB;
-extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB;
+extern PFNGLUNIFORMMATRIX4X3FVPROC glUniformMatrix4x3fv;
+
+// GL_VERSION_3_0
+extern PFNGLCOLORMASKIPROC glColorMaski;
+extern PFNGLGETBOOLEANI_VPROC glGetBooleani_v;
+extern PFNGLGETINTEGERI_VPROC glGetIntegeri_v;
+extern PFNGLENABLEIPROC glEnablei;
+extern PFNGLDISABLEIPROC glDisablei;
+extern PFNGLISENABLEDIPROC glIsEnabledi;
+extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;
+extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;
+extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange;
+extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;
+extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;
+extern PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glGetTransformFeedbackVarying;
+extern PFNGLCLAMPCOLORPROC glClampColor;
+extern PFNGLBEGINCONDITIONALRENDERPROC glBeginConditionalRender;
+extern PFNGLENDCONDITIONALRENDERPROC glEndConditionalRender;
+extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;
+extern PFNGLGETVERTEXATTRIBIIVPROC glGetVertexAttribIiv;
+extern PFNGLGETVERTEXATTRIBIUIVPROC glGetVertexAttribIuiv;
+extern PFNGLVERTEXATTRIBI1IPROC glVertexAttribI1i;
+extern PFNGLVERTEXATTRIBI2IPROC glVertexAttribI2i;
+extern PFNGLVERTEXATTRIBI3IPROC glVertexAttribI3i;
+extern PFNGLVERTEXATTRIBI4IPROC glVertexAttribI4i;
+extern PFNGLVERTEXATTRIBI1UIPROC glVertexAttribI1ui;
+extern PFNGLVERTEXATTRIBI2UIPROC glVertexAttribI2ui;
+extern PFNGLVERTEXATTRIBI3UIPROC glVertexAttribI3ui;
+extern PFNGLVERTEXATTRIBI4UIPROC glVertexAttribI4ui;
+extern PFNGLVERTEXATTRIBI1IVPROC glVertexAttribI1iv;
+extern PFNGLVERTEXATTRIBI2IVPROC glVertexAttribI2iv;
+extern PFNGLVERTEXATTRIBI3IVPROC glVertexAttribI3iv;
+extern PFNGLVERTEXATTRIBI4IVPROC glVertexAttribI4iv;
+extern PFNGLVERTEXATTRIBI1UIVPROC glVertexAttribI1uiv;
+extern PFNGLVERTEXATTRIBI2UIVPROC glVertexAttribI2uiv;
+extern PFNGLVERTEXATTRIBI3UIVPROC glVertexAttribI3uiv;
+extern PFNGLVERTEXATTRIBI4UIVPROC glVertexAttribI4uiv;
+extern PFNGLVERTEXATTRIBI4BVPROC glVertexAttribI4bv;
+extern PFNGLVERTEXATTRIBI4SVPROC glVertexAttribI4sv;
+extern PFNGLVERTEXATTRIBI4UBVPROC glVertexAttribI4ubv;
+extern PFNGLVERTEXATTRIBI4USVPROC glVertexAttribI4usv;
+extern PFNGLGETUNIFORMUIVPROC glGetUniformuiv;
+extern PFNGLBINDFRAGDATALOCATIONPROC glBindFragDataLocation;
+extern PFNGLGETFRAGDATALOCATIONPROC glGetFragDataLocation;
+extern PFNGLUNIFORM1UIPROC glUniform1ui;
+extern PFNGLUNIFORM2UIPROC glUniform2ui;
+extern PFNGLUNIFORM3UIPROC glUniform3ui;
+extern PFNGLUNIFORM4UIPROC glUniform4ui;
+extern PFNGLUNIFORM1UIVPROC glUniform1uiv;
+extern PFNGLUNIFORM2UIVPROC glUniform2uiv;
+extern PFNGLUNIFORM3UIVPROC glUniform3uiv;
+extern PFNGLUNIFORM4UIVPROC glUniform4uiv;
+extern PFNGLTEXPARAMETERIIVPROC glTexParameterIiv;
+extern PFNGLTEXPARAMETERIUIVPROC glTexParameterIuiv;
+extern PFNGLGETTEXPARAMETERIIVPROC glGetTexParameterIiv;
+extern PFNGLGETTEXPARAMETERIUIVPROC glGetTexParameterIuiv;
+extern PFNGLCLEARBUFFERIVPROC glClearBufferiv;
+extern PFNGLCLEARBUFFERUIVPROC glClearBufferuiv;
+extern PFNGLCLEARBUFFERFVPROC glClearBufferfv;
+extern PFNGLCLEARBUFFERFIPROC glClearBufferfi;
+extern PFNGLGETSTRINGIPROC glGetStringi;
+extern PFNGLISRENDERBUFFERPROC glIsRenderbuffer;
+extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
+extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
+extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
+extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
+extern PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv;
+extern PFNGLISFRAMEBUFFERPROC glIsFramebuffer;
+extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
+extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
+extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
+extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
+extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D;
+extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
+extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D;
+extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
+extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv;
+extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
+extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer;
+extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample;
+extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
+extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
+extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
+extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
+extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
+extern PFNGLISVERTEXARRAYPROC glIsVertexArray;
+
+// GL_VERSION_3_1
+extern PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced;
+extern PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced;
+extern PFNGLTEXBUFFERPROC glTexBuffer;
+extern PFNGLPRIMITIVERESTARTINDEXPROC glPrimitiveRestartIndex;
+extern PFNGLCOPYBUFFERSUBDATAPROC glCopyBufferSubData;
+extern PFNGLGETUNIFORMINDICESPROC glGetUniformIndices;
+extern PFNGLGETACTIVEUNIFORMSIVPROC glGetActiveUniformsiv;
+extern PFNGLGETACTIVEUNIFORMNAMEPROC glGetActiveUniformName;
+extern PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex;
+extern PFNGLGETACTIVEUNIFORMBLOCKIVPROC glGetActiveUniformBlockiv;
+extern PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glGetActiveUniformBlockName;
+extern PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding;
+
+// GL_VERSION_3_2
+extern PFNGLDRAWELEMENTSBASEVERTEXPROC glDrawElementsBaseVertex;
+extern PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glDrawRangeElementsBaseVertex;
+extern PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glDrawElementsInstancedBaseVertex;
+extern PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glMultiDrawElementsBaseVertex;
+extern PFNGLPROVOKINGVERTEXPROC glProvokingVertex;
+extern PFNGLFENCESYNCPROC glFenceSync;
+extern PFNGLISSYNCPROC glIsSync;
+extern PFNGLDELETESYNCPROC glDeleteSync;
+extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync;
+extern PFNGLWAITSYNCPROC glWaitSync;
+extern PFNGLGETINTEGER64VPROC glGetInteger64v;
+extern PFNGLGETSYNCIVPROC glGetSynciv;
+extern PFNGLGETINTEGER64I_VPROC glGetInteger64i_v;
+extern PFNGLGETBUFFERPARAMETERI64VPROC glGetBufferParameteri64v;
+extern PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture;
+extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
+extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
+extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
+extern PFNGLSAMPLEMASKIPROC glSampleMaski;
+
+// GL_VERSION_3_3
+extern PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glBindFragDataLocationIndexed;
+extern PFNGLGETFRAGDATAINDEXPROC glGetFragDataIndex;
+extern PFNGLGENSAMPLERSPROC glGenSamplers;
+extern PFNGLDELETESAMPLERSPROC glDeleteSamplers;
+extern PFNGLISSAMPLERPROC glIsSampler;
+extern PFNGLBINDSAMPLERPROC glBindSampler;
+extern PFNGLSAMPLERPARAMETERIPROC glSamplerParameteri;
+extern PFNGLSAMPLERPARAMETERIVPROC glSamplerParameteriv;
+extern PFNGLSAMPLERPARAMETERFPROC glSamplerParameterf;
+extern PFNGLSAMPLERPARAMETERFVPROC glSamplerParameterfv;
+extern PFNGLSAMPLERPARAMETERIIVPROC glSamplerParameterIiv;
+extern PFNGLSAMPLERPARAMETERIUIVPROC glSamplerParameterIuiv;
+extern PFNGLGETSAMPLERPARAMETERIVPROC glGetSamplerParameteriv;
+extern PFNGLGETSAMPLERPARAMETERIIVPROC glGetSamplerParameterIiv;
+extern PFNGLGETSAMPLERPARAMETERFVPROC glGetSamplerParameterfv;
+extern PFNGLGETSAMPLERPARAMETERIUIVPROC glGetSamplerParameterIuiv;
+extern PFNGLQUERYCOUNTERPROC glQueryCounter;
+extern PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v;
+extern PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v;
+extern PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor;
+extern PFNGLVERTEXATTRIBP1UIPROC glVertexAttribP1ui;
+extern PFNGLVERTEXATTRIBP1UIVPROC glVertexAttribP1uiv;
+extern PFNGLVERTEXATTRIBP2UIPROC glVertexAttribP2ui;
+extern PFNGLVERTEXATTRIBP2UIVPROC glVertexAttribP2uiv;
+extern PFNGLVERTEXATTRIBP3UIPROC glVertexAttribP3ui;
+extern PFNGLVERTEXATTRIBP3UIVPROC glVertexAttribP3uiv;
+extern PFNGLVERTEXATTRIBP4UIPROC glVertexAttribP4ui;
+extern PFNGLVERTEXATTRIBP4UIVPROC glVertexAttribP4uiv;
+extern PFNGLVERTEXP2UIPROC glVertexP2ui;
+extern PFNGLVERTEXP2UIVPROC glVertexP2uiv;
+extern PFNGLVERTEXP3UIPROC glVertexP3ui;
+extern PFNGLVERTEXP3UIVPROC glVertexP3uiv;
+extern PFNGLVERTEXP4UIPROC glVertexP4ui;
+extern PFNGLVERTEXP4UIVPROC glVertexP4uiv;
+extern PFNGLTEXCOORDP1UIPROC glTexCoordP1ui;
+extern PFNGLTEXCOORDP1UIVPROC glTexCoordP1uiv;
+extern PFNGLTEXCOORDP2UIPROC glTexCoordP2ui;
+extern PFNGLTEXCOORDP2UIVPROC glTexCoordP2uiv;
+extern PFNGLTEXCOORDP3UIPROC glTexCoordP3ui;
+extern PFNGLTEXCOORDP3UIVPROC glTexCoordP3uiv;
+extern PFNGLTEXCOORDP4UIPROC glTexCoordP4ui;
+extern PFNGLTEXCOORDP4UIVPROC glTexCoordP4uiv;
+extern PFNGLMULTITEXCOORDP1UIPROC glMultiTexCoordP1ui;
+extern PFNGLMULTITEXCOORDP1UIVPROC glMultiTexCoordP1uiv;
+extern PFNGLMULTITEXCOORDP2UIPROC glMultiTexCoordP2ui;
+extern PFNGLMULTITEXCOORDP2UIVPROC glMultiTexCoordP2uiv;
+extern PFNGLMULTITEXCOORDP3UIPROC glMultiTexCoordP3ui;
+extern PFNGLMULTITEXCOORDP3UIVPROC glMultiTexCoordP3uiv;
+extern PFNGLMULTITEXCOORDP4UIPROC glMultiTexCoordP4ui;
+extern PFNGLMULTITEXCOORDP4UIVPROC glMultiTexCoordP4uiv;
+extern PFNGLNORMALP3UIPROC glNormalP3ui;
+extern PFNGLNORMALP3UIVPROC glNormalP3uiv;
+extern PFNGLCOLORP3UIPROC glColorP3ui;
+extern PFNGLCOLORP3UIVPROC glColorP3uiv;
+extern PFNGLCOLORP4UIPROC glColorP4ui;
+extern PFNGLCOLORP4UIVPROC glColorP4uiv;
+extern PFNGLSECONDARYCOLORP3UIPROC glSecondaryColorP3ui;
+extern PFNGLSECONDARYCOLORP3UIVPROC glSecondaryColorP3uiv;
+
+// GL_VERSION_4_0
+extern PFNGLMINSAMPLESHADINGPROC glMinSampleShading;
+extern PFNGLBLENDEQUATIONIPROC glBlendEquationi;
+extern PFNGLBLENDEQUATIONSEPARATEIPROC glBlendEquationSeparatei;
+extern PFNGLBLENDFUNCIPROC glBlendFunci;
+extern PFNGLBLENDFUNCSEPARATEIPROC glBlendFuncSeparatei;
+extern PFNGLDRAWARRAYSINDIRECTPROC glDrawArraysIndirect;
+extern PFNGLDRAWELEMENTSINDIRECTPROC glDrawElementsIndirect;
+extern PFNGLUNIFORM1DPROC glUniform1d;
+extern PFNGLUNIFORM2DPROC glUniform2d;
+extern PFNGLUNIFORM3DPROC glUniform3d;
+extern PFNGLUNIFORM4DPROC glUniform4d;
+extern PFNGLUNIFORM1DVPROC glUniform1dv;
+extern PFNGLUNIFORM2DVPROC glUniform2dv;
+extern PFNGLUNIFORM3DVPROC glUniform3dv;
+extern PFNGLUNIFORM4DVPROC glUniform4dv;
+extern PFNGLUNIFORMMATRIX2DVPROC glUniformMatrix2dv;
+extern PFNGLUNIFORMMATRIX3DVPROC glUniformMatrix3dv;
+extern PFNGLUNIFORMMATRIX4DVPROC glUniformMatrix4dv;
+extern PFNGLUNIFORMMATRIX2X3DVPROC glUniformMatrix2x3dv;
+extern PFNGLUNIFORMMATRIX2X4DVPROC glUniformMatrix2x4dv;
+extern PFNGLUNIFORMMATRIX3X2DVPROC glUniformMatrix3x2dv;
+extern PFNGLUNIFORMMATRIX3X4DVPROC glUniformMatrix3x4dv;
+extern PFNGLUNIFORMMATRIX4X2DVPROC glUniformMatrix4x2dv;
+extern PFNGLUNIFORMMATRIX4X3DVPROC glUniformMatrix4x3dv;
+extern PFNGLGETUNIFORMDVPROC glGetUniformdv;
+extern PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC glGetSubroutineUniformLocation;
+extern PFNGLGETSUBROUTINEINDEXPROC glGetSubroutineIndex;
+extern PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC glGetActiveSubroutineUniformiv;
+extern PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC glGetActiveSubroutineUniformName;
+extern PFNGLGETACTIVESUBROUTINENAMEPROC glGetActiveSubroutineName;
+extern PFNGLUNIFORMSUBROUTINESUIVPROC glUniformSubroutinesuiv;
+extern PFNGLGETUNIFORMSUBROUTINEUIVPROC glGetUniformSubroutineuiv;
+extern PFNGLGETPROGRAMSTAGEIVPROC glGetProgramStageiv;
+extern PFNGLPATCHPARAMETERIPROC glPatchParameteri;
+extern PFNGLPATCHPARAMETERFVPROC glPatchParameterfv;
+extern PFNGLBINDTRANSFORMFEEDBACKPROC glBindTransformFeedback;
+extern PFNGLDELETETRANSFORMFEEDBACKSPROC glDeleteTransformFeedbacks;
+extern PFNGLGENTRANSFORMFEEDBACKSPROC glGenTransformFeedbacks;
+extern PFNGLISTRANSFORMFEEDBACKPROC glIsTransformFeedback;
+extern PFNGLPAUSETRANSFORMFEEDBACKPROC glPauseTransformFeedback;
+extern PFNGLRESUMETRANSFORMFEEDBACKPROC glResumeTransformFeedback;
+extern PFNGLDRAWTRANSFORMFEEDBACKPROC glDrawTransformFeedback;
+extern PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC glDrawTransformFeedbackStream;
+extern PFNGLBEGINQUERYINDEXEDPROC glBeginQueryIndexed;
+extern PFNGLENDQUERYINDEXEDPROC glEndQueryIndexed;
+extern PFNGLGETQUERYINDEXEDIVPROC glGetQueryIndexediv;
+
+ // GL_VERSION_4_1
+extern PFNGLRELEASESHADERCOMPILERPROC glReleaseShaderCompiler;
+extern PFNGLSHADERBINARYPROC glShaderBinary;
+extern PFNGLGETSHADERPRECISIONFORMATPROC glGetShaderPrecisionFormat;
+extern PFNGLDEPTHRANGEFPROC glDepthRangef;
+extern PFNGLCLEARDEPTHFPROC glClearDepthf;
+extern PFNGLGETPROGRAMBINARYPROC glGetProgramBinary;
+extern PFNGLPROGRAMBINARYPROC glProgramBinary;
+extern PFNGLPROGRAMPARAMETERIPROC glProgramParameteri;
+extern PFNGLUSEPROGRAMSTAGESPROC glUseProgramStages;
+extern PFNGLACTIVESHADERPROGRAMPROC glActiveShaderProgram;
+extern PFNGLCREATESHADERPROGRAMVPROC glCreateShaderProgramv;
+extern PFNGLBINDPROGRAMPIPELINEPROC glBindProgramPipeline;
+extern PFNGLDELETEPROGRAMPIPELINESPROC glDeleteProgramPipelines;
+extern PFNGLGENPROGRAMPIPELINESPROC glGenProgramPipelines;
+extern PFNGLISPROGRAMPIPELINEPROC glIsProgramPipeline;
+extern PFNGLGETPROGRAMPIPELINEIVPROC glGetProgramPipelineiv;
+extern PFNGLPROGRAMUNIFORM1IPROC glProgramUniform1i;
+extern PFNGLPROGRAMUNIFORM1IVPROC glProgramUniform1iv;
+extern PFNGLPROGRAMUNIFORM1FPROC glProgramUniform1f;
+extern PFNGLPROGRAMUNIFORM1FVPROC glProgramUniform1fv;
+extern PFNGLPROGRAMUNIFORM1DPROC glProgramUniform1d;
+extern PFNGLPROGRAMUNIFORM1DVPROC glProgramUniform1dv;
+extern PFNGLPROGRAMUNIFORM1UIPROC glProgramUniform1ui;
+extern PFNGLPROGRAMUNIFORM1UIVPROC glProgramUniform1uiv;
+extern PFNGLPROGRAMUNIFORM2IPROC glProgramUniform2i;
+extern PFNGLPROGRAMUNIFORM2IVPROC glProgramUniform2iv;
+extern PFNGLPROGRAMUNIFORM2FPROC glProgramUniform2f;
+extern PFNGLPROGRAMUNIFORM2FVPROC glProgramUniform2fv;
+extern PFNGLPROGRAMUNIFORM2DPROC glProgramUniform2d;
+extern PFNGLPROGRAMUNIFORM2DVPROC glProgramUniform2dv;
+extern PFNGLPROGRAMUNIFORM2UIPROC glProgramUniform2ui;
+extern PFNGLPROGRAMUNIFORM2UIVPROC glProgramUniform2uiv;
+extern PFNGLPROGRAMUNIFORM3IPROC glProgramUniform3i;
+extern PFNGLPROGRAMUNIFORM3IVPROC glProgramUniform3iv;
+extern PFNGLPROGRAMUNIFORM3FPROC glProgramUniform3f;
+extern PFNGLPROGRAMUNIFORM3FVPROC glProgramUniform3fv;
+extern PFNGLPROGRAMUNIFORM3DPROC glProgramUniform3d;
+extern PFNGLPROGRAMUNIFORM3DVPROC glProgramUniform3dv;
+extern PFNGLPROGRAMUNIFORM3UIPROC glProgramUniform3ui;
+extern PFNGLPROGRAMUNIFORM3UIVPROC glProgramUniform3uiv;
+extern PFNGLPROGRAMUNIFORM4IPROC glProgramUniform4i;
+extern PFNGLPROGRAMUNIFORM4IVPROC glProgramUniform4iv;
+extern PFNGLPROGRAMUNIFORM4FPROC glProgramUniform4f;
+extern PFNGLPROGRAMUNIFORM4FVPROC glProgramUniform4fv;
+extern PFNGLPROGRAMUNIFORM4DPROC glProgramUniform4d;
+extern PFNGLPROGRAMUNIFORM4DVPROC glProgramUniform4dv;
+extern PFNGLPROGRAMUNIFORM4UIPROC glProgramUniform4ui;
+extern PFNGLPROGRAMUNIFORM4UIVPROC glProgramUniform4uiv;
+extern PFNGLPROGRAMUNIFORMMATRIX2FVPROC glProgramUniformMatrix2fv;
+extern PFNGLPROGRAMUNIFORMMATRIX3FVPROC glProgramUniformMatrix3fv;
+extern PFNGLPROGRAMUNIFORMMATRIX4FVPROC glProgramUniformMatrix4fv;
+extern PFNGLPROGRAMUNIFORMMATRIX2DVPROC glProgramUniformMatrix2dv;
+extern PFNGLPROGRAMUNIFORMMATRIX3DVPROC glProgramUniformMatrix3dv;
+extern PFNGLPROGRAMUNIFORMMATRIX4DVPROC glProgramUniformMatrix4dv;
+extern PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC glProgramUniformMatrix2x3fv;
+extern PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC glProgramUniformMatrix3x2fv;
+extern PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC glProgramUniformMatrix2x4fv;
+extern PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC glProgramUniformMatrix4x2fv;
+extern PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC glProgramUniformMatrix3x4fv;
+extern PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC glProgramUniformMatrix4x3fv;
+extern PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC glProgramUniformMatrix2x3dv;
+extern PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC glProgramUniformMatrix3x2dv;
+extern PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC glProgramUniformMatrix2x4dv;
+extern PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC glProgramUniformMatrix4x2dv;
+extern PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC glProgramUniformMatrix3x4dv;
+extern PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC glProgramUniformMatrix4x3dv;
+extern PFNGLVALIDATEPROGRAMPIPELINEPROC glValidateProgramPipeline;
+extern PFNGLGETPROGRAMPIPELINEINFOLOGPROC glGetProgramPipelineInfoLog;
+extern PFNGLVERTEXATTRIBL1DPROC glVertexAttribL1d;
+extern PFNGLVERTEXATTRIBL2DPROC glVertexAttribL2d;
+extern PFNGLVERTEXATTRIBL3DPROC glVertexAttribL3d;
+extern PFNGLVERTEXATTRIBL4DPROC glVertexAttribL4d;
+extern PFNGLVERTEXATTRIBL1DVPROC glVertexAttribL1dv;
+extern PFNGLVERTEXATTRIBL2DVPROC glVertexAttribL2dv;
+extern PFNGLVERTEXATTRIBL3DVPROC glVertexAttribL3dv;
+extern PFNGLVERTEXATTRIBL4DVPROC glVertexAttribL4dv;
+extern PFNGLVERTEXATTRIBLPOINTERPROC glVertexAttribLPointer;
+extern PFNGLGETVERTEXATTRIBLDVPROC glGetVertexAttribLdv;
+extern PFNGLVIEWPORTARRAYVPROC glViewportArrayv;
+extern PFNGLVIEWPORTINDEXEDFPROC glViewportIndexedf;
+extern PFNGLVIEWPORTINDEXEDFVPROC glViewportIndexedfv;
+extern PFNGLSCISSORARRAYVPROC glScissorArrayv;
+extern PFNGLSCISSORINDEXEDPROC glScissorIndexed;
+extern PFNGLSCISSORINDEXEDVPROC glScissorIndexedv;
+extern PFNGLDEPTHRANGEARRAYVPROC glDepthRangeArrayv;
+extern PFNGLDEPTHRANGEINDEXEDPROC glDepthRangeIndexed;
+extern PFNGLGETFLOATI_VPROC glGetFloati_v;
+extern PFNGLGETDOUBLEI_VPROC glGetDoublei_v;
+
+// GL_VERSION_4_2
+extern PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC glDrawArraysInstancedBaseInstance;
+extern PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC glDrawElementsInstancedBaseInstance;
+extern PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC glDrawElementsInstancedBaseVertexBaseInstance;
+extern PFNGLGETINTERNALFORMATIVPROC glGetInternalformativ;
+extern PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC glGetActiveAtomicCounterBufferiv;
+extern PFNGLBINDIMAGETEXTUREPROC glBindImageTexture;
+extern PFNGLMEMORYBARRIERPROC glMemoryBarrier;
+extern PFNGLTEXSTORAGE1DPROC glTexStorage1D;
+extern PFNGLTEXSTORAGE2DPROC glTexStorage2D;
+extern PFNGLTEXSTORAGE3DPROC glTexStorage3D;
+extern PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC glDrawTransformFeedbackInstanced;
+extern PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC glDrawTransformFeedbackStreamInstanced;
+
+// GL_VERSION_4_3
+extern PFNGLCLEARBUFFERDATAPROC glClearBufferData;
+extern PFNGLCLEARBUFFERSUBDATAPROC glClearBufferSubData;
+extern PFNGLDISPATCHCOMPUTEPROC glDispatchCompute;
+extern PFNGLDISPATCHCOMPUTEINDIRECTPROC glDispatchComputeIndirect;
+extern PFNGLCOPYIMAGESUBDATAPROC glCopyImageSubData;
+extern PFNGLFRAMEBUFFERPARAMETERIPROC glFramebufferParameteri;
+extern PFNGLGETFRAMEBUFFERPARAMETERIVPROC glGetFramebufferParameteriv;
+extern PFNGLGETINTERNALFORMATI64VPROC glGetInternalformati64v;
+extern PFNGLINVALIDATETEXSUBIMAGEPROC glInvalidateTexSubImage;
+extern PFNGLINVALIDATETEXIMAGEPROC glInvalidateTexImage;
+extern PFNGLINVALIDATEBUFFERSUBDATAPROC glInvalidateBufferSubData;
+extern PFNGLINVALIDATEBUFFERDATAPROC glInvalidateBufferData;
+extern PFNGLINVALIDATEFRAMEBUFFERPROC glInvalidateFramebuffer;
+extern PFNGLINVALIDATESUBFRAMEBUFFERPROC glInvalidateSubFramebuffer;
+extern PFNGLMULTIDRAWARRAYSINDIRECTPROC glMultiDrawArraysIndirect;
+extern PFNGLMULTIDRAWELEMENTSINDIRECTPROC glMultiDrawElementsIndirect;
+extern PFNGLGETPROGRAMINTERFACEIVPROC glGetProgramInterfaceiv;
+extern PFNGLGETPROGRAMRESOURCEINDEXPROC glGetProgramResourceIndex;
+extern PFNGLGETPROGRAMRESOURCENAMEPROC glGetProgramResourceName;
+extern PFNGLGETPROGRAMRESOURCEIVPROC glGetProgramResourceiv;
+extern PFNGLGETPROGRAMRESOURCELOCATIONPROC glGetProgramResourceLocation;
+extern PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC glGetProgramResourceLocationIndex;
+extern PFNGLSHADERSTORAGEBLOCKBINDINGPROC glShaderStorageBlockBinding;
+extern PFNGLTEXBUFFERRANGEPROC glTexBufferRange;
+extern PFNGLTEXSTORAGE2DMULTISAMPLEPROC glTexStorage2DMultisample;
+extern PFNGLTEXSTORAGE3DMULTISAMPLEPROC glTexStorage3DMultisample;
+extern PFNGLTEXTUREVIEWPROC glTextureView;
+extern PFNGLBINDVERTEXBUFFERPROC glBindVertexBuffer;
+extern PFNGLVERTEXATTRIBFORMATPROC glVertexAttribFormat;
+extern PFNGLVERTEXATTRIBIFORMATPROC glVertexAttribIFormat;
+extern PFNGLVERTEXATTRIBLFORMATPROC glVertexAttribLFormat;
+extern PFNGLVERTEXATTRIBBINDINGPROC glVertexAttribBinding;
+extern PFNGLVERTEXBINDINGDIVISORPROC glVertexBindingDivisor;
+extern PFNGLDEBUGMESSAGECONTROLPROC glDebugMessageControl;
+extern PFNGLDEBUGMESSAGEINSERTPROC glDebugMessageInsert;
+extern PFNGLDEBUGMESSAGECALLBACKPROC glDebugMessageCallback;
+extern PFNGLGETDEBUGMESSAGELOGPROC glGetDebugMessageLog;
+extern PFNGLPUSHDEBUGGROUPPROC glPushDebugGroup;
+extern PFNGLPOPDEBUGGROUPPROC glPopDebugGroup;
+extern PFNGLOBJECTLABELPROC glObjectLabel;
+extern PFNGLGETOBJECTLABELPROC glGetObjectLabel;
+extern PFNGLOBJECTPTRLABELPROC glObjectPtrLabel;
+extern PFNGLGETOBJECTPTRLABELPROC glGetObjectPtrLabel;
+
+// GL_VERSION_4_4
+extern PFNGLBUFFERSTORAGEPROC glBufferStorage;
+extern PFNGLCLEARTEXIMAGEPROC glClearTexImage;
+extern PFNGLCLEARTEXSUBIMAGEPROC glClearTexSubImage;
+extern PFNGLBINDBUFFERSBASEPROC glBindBuffersBase;
+extern PFNGLBINDBUFFERSRANGEPROC glBindBuffersRange;
+extern PFNGLBINDTEXTURESPROC glBindTextures;
+extern PFNGLBINDSAMPLERSPROC glBindSamplers;
+extern PFNGLBINDIMAGETEXTURESPROC glBindImageTextures;
+extern PFNGLBINDVERTEXBUFFERSPROC glBindVertexBuffers;
+
+// GL_VERSION_4_5
+extern PFNGLCLIPCONTROLPROC glClipControl;
+extern PFNGLCREATETRANSFORMFEEDBACKSPROC glCreateTransformFeedbacks;
+extern PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC glTransformFeedbackBufferBase;
+extern PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC glTransformFeedbackBufferRange;
+extern PFNGLGETTRANSFORMFEEDBACKIVPROC glGetTransformFeedbackiv;
+extern PFNGLGETTRANSFORMFEEDBACKI_VPROC glGetTransformFeedbacki_v;
+extern PFNGLGETTRANSFORMFEEDBACKI64_VPROC glGetTransformFeedbacki64_v;
+extern PFNGLCREATEBUFFERSPROC glCreateBuffers;
+extern PFNGLNAMEDBUFFERSTORAGEPROC glNamedBufferStorage;
+extern PFNGLNAMEDBUFFERDATAPROC glNamedBufferData;
+extern PFNGLNAMEDBUFFERSUBDATAPROC glNamedBufferSubData;
+extern PFNGLCOPYNAMEDBUFFERSUBDATAPROC glCopyNamedBufferSubData;
+extern PFNGLCLEARNAMEDBUFFERDATAPROC glClearNamedBufferData;
+extern PFNGLCLEARNAMEDBUFFERSUBDATAPROC glClearNamedBufferSubData;
+extern PFNGLMAPNAMEDBUFFERPROC glMapNamedBuffer;
+extern PFNGLMAPNAMEDBUFFERRANGEPROC glMapNamedBufferRange;
+extern PFNGLUNMAPNAMEDBUFFERPROC glUnmapNamedBuffer;
+extern PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC glFlushMappedNamedBufferRange;
+extern PFNGLGETNAMEDBUFFERPARAMETERIVPROC glGetNamedBufferParameteriv;
+extern PFNGLGETNAMEDBUFFERPARAMETERI64VPROC glGetNamedBufferParameteri64v;
+extern PFNGLGETNAMEDBUFFERPOINTERVPROC glGetNamedBufferPointerv;
+extern PFNGLGETNAMEDBUFFERSUBDATAPROC glGetNamedBufferSubData;
+extern PFNGLCREATEFRAMEBUFFERSPROC glCreateFramebuffers;
+extern PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC glNamedFramebufferRenderbuffer;
+extern PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC glNamedFramebufferParameteri;
+extern PFNGLNAMEDFRAMEBUFFERTEXTUREPROC glNamedFramebufferTexture;
+extern PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC glNamedFramebufferTextureLayer;
+extern PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC glNamedFramebufferDrawBuffer;
+extern PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC glNamedFramebufferDrawBuffers;
+extern PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC glNamedFramebufferReadBuffer;
+extern PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC glInvalidateNamedFramebufferData;
+extern PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC glInvalidateNamedFramebufferSubData;
+extern PFNGLCLEARNAMEDFRAMEBUFFERIVPROC glClearNamedFramebufferiv;
+extern PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC glClearNamedFramebufferuiv;
+extern PFNGLCLEARNAMEDFRAMEBUFFERFVPROC glClearNamedFramebufferfv;
+extern PFNGLCLEARNAMEDFRAMEBUFFERFIPROC glClearNamedFramebufferfi;
+extern PFNGLBLITNAMEDFRAMEBUFFERPROC glBlitNamedFramebuffer;
+extern PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC glCheckNamedFramebufferStatus;
+extern PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC glGetNamedFramebufferParameteriv;
+extern PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetNamedFramebufferAttachmentParameteriv;
+extern PFNGLCREATERENDERBUFFERSPROC glCreateRenderbuffers;
+extern PFNGLNAMEDRENDERBUFFERSTORAGEPROC glNamedRenderbufferStorage;
+extern PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC glNamedRenderbufferStorageMultisample;
+extern PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC glGetNamedRenderbufferParameteriv;
+extern PFNGLCREATETEXTURESPROC glCreateTextures;
+extern PFNGLTEXTUREBUFFERPROC glTextureBuffer;
+extern PFNGLTEXTUREBUFFERRANGEPROC glTextureBufferRange;
+extern PFNGLTEXTURESTORAGE1DPROC glTextureStorage1D;
+extern PFNGLTEXTURESTORAGE2DPROC glTextureStorage2D;
+extern PFNGLTEXTURESTORAGE3DPROC glTextureStorage3D;
+extern PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC glTextureStorage2DMultisample;
+extern PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC glTextureStorage3DMultisample;
+extern PFNGLTEXTURESUBIMAGE1DPROC glTextureSubImage1D;
+extern PFNGLTEXTURESUBIMAGE2DPROC glTextureSubImage2D;
+extern PFNGLTEXTURESUBIMAGE3DPROC glTextureSubImage3D;
+extern PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC glCompressedTextureSubImage1D;
+extern PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC glCompressedTextureSubImage2D;
+extern PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC glCompressedTextureSubImage3D;
+extern PFNGLCOPYTEXTURESUBIMAGE1DPROC glCopyTextureSubImage1D;
+extern PFNGLCOPYTEXTURESUBIMAGE2DPROC glCopyTextureSubImage2D;
+extern PFNGLCOPYTEXTURESUBIMAGE3DPROC glCopyTextureSubImage3D;
+extern PFNGLTEXTUREPARAMETERFPROC glTextureParameterf;
+extern PFNGLTEXTUREPARAMETERFVPROC glTextureParameterfv;
+extern PFNGLTEXTUREPARAMETERIPROC glTextureParameteri;
+extern PFNGLTEXTUREPARAMETERIIVPROC glTextureParameterIiv;
+extern PFNGLTEXTUREPARAMETERIUIVPROC glTextureParameterIuiv;
+extern PFNGLTEXTUREPARAMETERIVPROC glTextureParameteriv;
+extern PFNGLGENERATETEXTUREMIPMAPPROC glGenerateTextureMipmap;
+extern PFNGLBINDTEXTUREUNITPROC glBindTextureUnit;
+extern PFNGLGETTEXTUREIMAGEPROC glGetTextureImage;
+extern PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC glGetCompressedTextureImage;
+extern PFNGLGETTEXTURELEVELPARAMETERFVPROC glGetTextureLevelParameterfv;
+extern PFNGLGETTEXTURELEVELPARAMETERIVPROC glGetTextureLevelParameteriv;
+extern PFNGLGETTEXTUREPARAMETERFVPROC glGetTextureParameterfv;
+extern PFNGLGETTEXTUREPARAMETERIIVPROC glGetTextureParameterIiv;
+extern PFNGLGETTEXTUREPARAMETERIUIVPROC glGetTextureParameterIuiv;
+extern PFNGLGETTEXTUREPARAMETERIVPROC glGetTextureParameteriv;
+extern PFNGLCREATEVERTEXARRAYSPROC glCreateVertexArrays;
+extern PFNGLDISABLEVERTEXARRAYATTRIBPROC glDisableVertexArrayAttrib;
+extern PFNGLENABLEVERTEXARRAYATTRIBPROC glEnableVertexArrayAttrib;
+extern PFNGLVERTEXARRAYELEMENTBUFFERPROC glVertexArrayElementBuffer;
+extern PFNGLVERTEXARRAYVERTEXBUFFERPROC glVertexArrayVertexBuffer;
+extern PFNGLVERTEXARRAYVERTEXBUFFERSPROC glVertexArrayVertexBuffers;
+extern PFNGLVERTEXARRAYATTRIBBINDINGPROC glVertexArrayAttribBinding;
+extern PFNGLVERTEXARRAYATTRIBFORMATPROC glVertexArrayAttribFormat;
+extern PFNGLVERTEXARRAYATTRIBIFORMATPROC glVertexArrayAttribIFormat;
+extern PFNGLVERTEXARRAYATTRIBLFORMATPROC glVertexArrayAttribLFormat;
+extern PFNGLVERTEXARRAYBINDINGDIVISORPROC glVertexArrayBindingDivisor;
+extern PFNGLGETVERTEXARRAYIVPROC glGetVertexArrayiv;
+extern PFNGLGETVERTEXARRAYINDEXEDIVPROC glGetVertexArrayIndexediv;
+extern PFNGLGETVERTEXARRAYINDEXED64IVPROC glGetVertexArrayIndexed64iv;
+extern PFNGLCREATESAMPLERSPROC glCreateSamplers;
+extern PFNGLCREATEPROGRAMPIPELINESPROC glCreateProgramPipelines;
+extern PFNGLCREATEQUERIESPROC glCreateQueries;
+extern PFNGLGETQUERYBUFFEROBJECTI64VPROC glGetQueryBufferObjecti64v;
+extern PFNGLGETQUERYBUFFEROBJECTIVPROC glGetQueryBufferObjectiv;
+extern PFNGLGETQUERYBUFFEROBJECTUI64VPROC glGetQueryBufferObjectui64v;
+extern PFNGLGETQUERYBUFFEROBJECTUIVPROC glGetQueryBufferObjectuiv;
+extern PFNGLMEMORYBARRIERBYREGIONPROC glMemoryBarrierByRegion;
+extern PFNGLGETTEXTURESUBIMAGEPROC glGetTextureSubImage;
+extern PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC glGetCompressedTextureSubImage;
+extern PFNGLGETGRAPHICSRESETSTATUSPROC glGetGraphicsResetStatus;
+extern PFNGLGETNCOMPRESSEDTEXIMAGEPROC glGetnCompressedTexImage;
+extern PFNGLGETNTEXIMAGEPROC glGetnTexImage;
+extern PFNGLGETNUNIFORMDVPROC glGetnUniformdv;
+extern PFNGLGETNUNIFORMFVPROC glGetnUniformfv;
+extern PFNGLGETNUNIFORMIVPROC glGetnUniformiv;
+extern PFNGLGETNUNIFORMUIVPROC glGetnUniformuiv;
+extern PFNGLREADNPIXELSPROC glReadnPixels;
+extern PFNGLGETNMAPDVPROC glGetnMapdv;
+extern PFNGLGETNMAPFVPROC glGetnMapfv;
+extern PFNGLGETNMAPIVPROC glGetnMapiv;
+extern PFNGLGETNPIXELMAPFVPROC glGetnPixelMapfv;
+extern PFNGLGETNPIXELMAPUIVPROC glGetnPixelMapuiv;
+extern PFNGLGETNPIXELMAPUSVPROC glGetnPixelMapusv;
+extern PFNGLGETNPOLYGONSTIPPLEPROC glGetnPolygonStipple;
+extern PFNGLGETNCOLORTABLEPROC glGetnColorTable;
+extern PFNGLGETNCONVOLUTIONFILTERPROC glGetnConvolutionFilter;
+extern PFNGLGETNSEPARABLEFILTERPROC glGetnSeparableFilter;
+extern PFNGLGETNHISTOGRAMPROC glGetnHistogram;
+extern PFNGLGETNMINMAXPROC glGetnMinmax;
+extern PFNGLTEXTUREBARRIERPROC glTextureBarrier;
+
+// GL_VERSION_4_6
+extern PFNGLSPECIALIZESHADERPROC glSpecializeShader;
+extern PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC glMultiDrawArraysIndirectCount;
+extern PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC glMultiDrawElementsIndirectCount;
+extern PFNGLPOLYGONOFFSETCLAMPPROC glPolygonOffsetClamp;
-//GL_EXT_blend_func_separate
-extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT;
-
-//GL_ARB_framebuffer_object
-extern PFNGLISRENDERBUFFERPROC glIsRenderbuffer;
-extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
-extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
-extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
-extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
-extern PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv;
-extern PFNGLISFRAMEBUFFERPROC glIsFramebuffer;
-extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
-extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
-extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
-extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
-extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D;
-extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
-extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D;
-extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
-extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv;
-extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
-extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer;
-extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample;
-extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
-
-//GL_ARB_draw_buffers
-extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;
-
-//GL_ARB_texture_multisample
-extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
-extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
-extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
-extern PFNGLSAMPLEMASKIPROC glSampleMaski;
-
-//transform feedback (4.0 core)
-extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;
-extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;
-extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;
-extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange;
-extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;
-
-//GL_ARB_debug_output
-extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB;
-extern PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB;
-extern PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB;
-extern PFNGLGETDEBUGMESSAGELOGARBPROC glGetDebugMessageLogARB;
#elif LL_DARWIN
//----------------------------------------------------------------------------
// LL_DARWIN
+#define GL_GLEXT_LEGACY
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#define GL_EXT_separate_specular_color 1
-#include <OpenGL/glext.h>
+#define GL_GLEXT_PROTOTYPES
+#include "GL/glext.h"
#include "GL/glh_extensions.h"
@@ -602,9 +858,6 @@ extern void glGenerateMipmapEXT(GLenum target) AVAILABLE_MAC_OS_X_VERSION_10_4_A
#define GL_MAX_SAMPLES 0x8D57
#endif
-// GL_ARB_draw_buffers
-extern void glDrawBuffersARB(GLsizei n, const GLenum* bufs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -689,8 +942,8 @@ extern "C" {
#ifndef GL_ARB_vertex_buffer_object
/* GL types for handling large vertex buffer objects */
-typedef intptr_t GLintptrARB;
-typedef intptr_t GLsizeiptrARB;
+typedef intptr_t GLintptr;
+typedef intptr_t GLsizeiptr;
#endif
@@ -808,22 +1061,8 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);
#endif
#if defined(TRACY_ENABLE) && LL_PROFILER_ENABLE_TRACY_OPENGL
- // Tracy uses the following:
- // glGenQueries
- // glGetQueryiv
- // glGetQueryObjectiv
- #define glGenQueries glGenQueriesARB
- #define glGetQueryiv glGetQueryivARB
- #define glGetQueryObjectiv glGetQueryObjectivARB
#include <tracy/TracyOpenGL.hpp>
-
- #define LL_PROFILER_GPU_ZONEC(name,color) TracyGpuZoneC(name,color);
- #define LL_PROFILER_GPU_COLLECT TracyGpuCollect
- #define LL_PROFILER_GPU_CONTEXT TracyGpuContext
-#else
- #define LL_PROFILER_GPU_ZONEC(name,color) (void)name;(void)color;
- #define LL_PROFILER_GPU_COLLECT
- #define LL_PROFILER_GPU_CONTEXT
#endif
+
#endif // LL_LLGLHEADERS_H
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index da24d999b0..ccfb8f69be 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llglslshader.cpp
* @brief GLSL helper functions and state.
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -32,13 +32,17 @@
#include "llfile.h"
#include "llrender.h"
#include "llvertexbuffer.h"
+#include "llrendertarget.h"
+
+#include "hbxxh.h"
+#include "llsdserialize.h"
#if LL_DARWIN
#include "OpenGL/OpenGL.h"
#endif
-// Print-print list of shader included source files that are linked together via glAttachObjectARB()
-// i.e. On macOS / OSX the AMD GLSL linker will display an error if a varying is left in an undefined state.
+ // Print-print list of shader included source files that are linked together via glAttachShader()
+ // i.e. On macOS / OSX the AMD GLSL linker will display an error if a varying is left in an undefined state.
#define DEBUG_SHADER_INCLUDES 0
// Lots of STL stuff in here, using namespace std to keep things more readable
@@ -47,51 +51,39 @@ using std::pair;
using std::make_pair;
using std::string;
-GLhandleARB LLGLSLShader::sCurBoundShader = 0;
+GLuint LLGLSLShader::sCurBoundShader = 0;
LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL;
S32 LLGLSLShader::sIndexedTextureChannels = 0;
bool LLGLSLShader::sProfileEnabled = false;
std::set<LLGLSLShader*> LLGLSLShader::sInstances;
+LLGLSLShader::defines_map_t LLGLSLShader::sGlobalDefines;
U64 LLGLSLShader::sTotalTimeElapsed = 0;
U32 LLGLSLShader::sTotalTrianglesDrawn = 0;
U64 LLGLSLShader::sTotalSamplesDrawn = 0;
-U32 LLGLSLShader::sTotalDrawCalls = 0;
+U32 LLGLSLShader::sTotalBinds = 0;
//UI shader -- declared here so llui_libtest will link properly
LLGLSLShader gUIProgram;
LLGLSLShader gSolidColorProgram;
-BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
+// NOTE: Keep gShaderConsts* and LLGLSLShader::ShaderConsts_e in sync!
+const std::string gShaderConstsKey[LLGLSLShader::NUM_SHADER_CONSTS] =
{
- return v1 != v2;
-}
+ "LL_SHADER_CONST_CLOUD_MOON_DEPTH"
+ , "LL_SHADER_CONST_STAR_DEPTH"
+};
-LLShaderFeatures::LLShaderFeatures()
- : atmosphericHelpers(false)
- , calculatesLighting(false)
- , calculatesAtmospherics(false)
- , hasLighting(false)
- , isAlphaLighting(false)
- , isShiny(false)
- , isFullbright(false)
- , isSpecular(false)
- , hasWaterFog(false)
- , hasTransport(false)
- , hasSkinning(false)
- , hasObjectSkinning(false)
- , hasAtmospherics(false)
- , hasGamma(false)
- , hasSrgb(false)
- , encodesNormal(false)
- , isDeferred(false)
- , hasIndirect(false)
- , hasShadows(false)
- , hasAmbientOcclusion(false)
- , mIndexedTextureChannels(0)
- , disableTextureIndex(false)
- , hasAlphaMask(false)
- , attachNothing(false)
+// NOTE: Keep gShaderConsts* and LLGLSLShader::ShaderConsts_e in sync!
+const std::string gShaderConstsVal[LLGLSLShader::NUM_SHADER_CONSTS] =
{
+ "0.99998" // SHADER_CONST_CLOUD_MOON_DEPTH // SL-14113
+ , "0.99999" // SHADER_CONST_STAR_DEPTH // SL-14113
+};
+
+
+BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
+{
+ return v1 != v2;
}
//===============================
@@ -105,7 +97,7 @@ void LLGLSLShader::initProfile()
sTotalTimeElapsed = 0;
sTotalTrianglesDrawn = 0;
sTotalSamplesDrawn = 0;
- sTotalDrawCalls = 0;
+ sTotalBinds = 0;
for (std::set<LLGLSLShader*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter)
{
@@ -116,10 +108,10 @@ void LLGLSLShader::initProfile()
struct LLGLSLShaderCompareTimeElapsed
{
- bool operator()(const LLGLSLShader* const& lhs, const LLGLSLShader* const& rhs)
- {
- return lhs->mTimeElapsed < rhs->mTimeElapsed;
- }
+ bool operator()(const LLGLSLShader* const& lhs, const LLGLSLShader* const& rhs)
+ {
+ return lhs->mTimeElapsed < rhs->mTimeElapsed;
+ }
};
//static
@@ -138,15 +130,33 @@ void LLGLSLShader::finishProfile(bool emit_report)
std::sort(sorted.begin(), sorted.end(), LLGLSLShaderCompareTimeElapsed());
+ bool unbound = false;
for (std::vector<LLGLSLShader*>::iterator iter = sorted.begin(); iter != sorted.end(); ++iter)
{
(*iter)->dumpStats();
+ if ((*iter)->mBinds == 0)
+ {
+ unbound = true;
+ }
+ }
+
+ LL_INFOS() << "-----------------------------------" << LL_ENDL;
+ LL_INFOS() << "Total rendering time: " << llformat("%.4f ms", sTotalTimeElapsed / 1000000.f) << LL_ENDL;
+ LL_INFOS() << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn / 1000000.f) << LL_ENDL;
+ LL_INFOS() << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn / 1000000.f) << LL_ENDL;
+ LL_INFOS() << "-----------------------------------" << LL_ENDL;
+
+ if (unbound)
+ {
+ LL_INFOS() << "The following shaders were unused: " << LL_ENDL;
+ for (std::vector<LLGLSLShader*>::iterator iter = sorted.begin(); iter != sorted.end(); ++iter)
+ {
+ if ((*iter)->mBinds == 0)
+ {
+ LL_INFOS() << (*iter)->mName << LL_ENDL;
+ }
+ }
}
-
- LL_INFOS() << "-----------------------------------" << LL_ENDL;
- LL_INFOS() << "Total rendering time: " << llformat("%.4f ms", sTotalTimeElapsed/1000000.f) << LL_ENDL;
- LL_INFOS() << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn/1000000.f) << LL_ENDL;
- LL_INFOS() << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn/1000000.f) << LL_ENDL;
}
}
@@ -155,15 +165,12 @@ void LLGLSLShader::clearStats()
mTrianglesDrawn = 0;
mTimeElapsed = 0;
mSamplesDrawn = 0;
- mDrawCalls = 0;
- mTextureStateFetched = false;
- mTextureMagFilter.clear();
- mTextureMinFilter.clear();
+ mBinds = 0;
}
void LLGLSLShader::dumpStats()
{
- if (mDrawCalls > 0)
+ if (mBinds > 0)
{
LL_INFOS() << "=============================================" << LL_ENDL;
LL_INFOS() << mName << LL_ENDL;
@@ -171,36 +178,25 @@ void LLGLSLShader::dumpStats()
{
LL_INFOS() << mShaderFiles[i].first << LL_ENDL;
}
- for (U32 i = 0; i < mTexture.size(); ++i)
- {
- GLint idx = mTexture[i];
-
- if (idx >= 0)
- {
- GLint uniform_idx = getUniformLocation(i);
- LL_INFOS() << mUniformNameMap[uniform_idx] << " - " << std::hex << mTextureMagFilter[i] << "/" << mTextureMinFilter[i] << std::dec << LL_ENDL;
- }
- }
LL_INFOS() << "=============================================" << LL_ENDL;
-
- F32 ms = mTimeElapsed/1000000.f;
- F32 seconds = ms/1000.f;
- F32 pct_tris = (F32) mTrianglesDrawn/(F32)sTotalTrianglesDrawn*100.f;
- F32 tris_sec = (F32) (mTrianglesDrawn/1000000.0);
+ F32 ms = mTimeElapsed / 1000000.f;
+ F32 seconds = ms / 1000.f;
+
+ F32 pct_tris = (F32)mTrianglesDrawn / (F32)sTotalTrianglesDrawn * 100.f;
+ F32 tris_sec = (F32)(mTrianglesDrawn / 1000000.0);
tris_sec /= seconds;
- F32 pct_samples = (F32) ((F64)mSamplesDrawn/(F64)sTotalSamplesDrawn)*100.f;
- F32 samples_sec = (F32) mSamplesDrawn/1000000000.0;
+ F32 pct_samples = (F32)((F64)mSamplesDrawn / (F64)sTotalSamplesDrawn) * 100.f;
+ F32 samples_sec = (F32)mSamplesDrawn / 1000000000.0;
samples_sec /= seconds;
- F32 pct_calls = (F32) mDrawCalls/(F32)sTotalDrawCalls*100.f;
- U32 avg_batch = mTrianglesDrawn/mDrawCalls;
+ F32 pct_binds = (F32)mBinds / (F32)sTotalBinds * 100.f;
- LL_INFOS() << "Triangles Drawn: " << mTrianglesDrawn << " " << llformat("(%.2f pct of total, %.3f million/sec)", pct_tris, tris_sec ) << LL_ENDL;
- LL_INFOS() << "Draw Calls: " << mDrawCalls << " " << llformat("(%.2f pct of total, avg %d tris/call)", pct_calls, avg_batch) << LL_ENDL;
+ LL_INFOS() << "Triangles Drawn: " << mTrianglesDrawn << " " << llformat("(%.2f pct of total, %.3f million/sec)", pct_tris, tris_sec) << LL_ENDL;
+ LL_INFOS() << "Binds: " << mBinds << " " << llformat("(%.2f pct of total)", pct_binds) << LL_ENDL;
LL_INFOS() << "SamplesDrawn: " << mSamplesDrawn << " " << llformat("(%.2f pct of total, %.3f billion/sec)", pct_samples, samples_sec) << LL_ENDL;
- LL_INFOS() << "Time Elapsed: " << mTimeElapsed << " " << llformat("(%.2f pct of total, %.5f ms)\n", (F32) ((F64)mTimeElapsed/(F64)sTotalTimeElapsed)*100.f, ms) << LL_ENDL;
+ LL_INFOS() << "Time Elapsed: " << mTimeElapsed << " " << llformat("(%.2f pct of total, %.5f ms)\n", (F32)((F64)mTimeElapsed / (F64)sTotalTimeElapsed) * 100.f, ms) << LL_ENDL;
}
}
@@ -216,112 +212,109 @@ void LLGLSLShader::startProfile()
}
//static
-void LLGLSLShader::stopProfile(U32 count, U32 mode)
+void LLGLSLShader::stopProfile()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+
if (sProfileEnabled && sCurBoundShaderPtr)
{
- sCurBoundShaderPtr->readProfileQuery(count, mode);
+ sCurBoundShaderPtr->unbind();
}
}
-void LLGLSLShader::placeProfileQuery()
+void LLGLSLShader::placeProfileQuery(bool for_runtime)
{
-#if !LL_DARWIN
- if (mTimerQuery == 0)
- {
- glGenQueriesARB(1, &mSamplesQuery);
- glGenQueriesARB(1, &mTimerQuery);
- }
-
- if (!mTextureStateFetched)
+ if (sProfileEnabled || for_runtime)
{
- mTextureStateFetched = true;
- mTextureMagFilter.resize(mTexture.size());
- mTextureMinFilter.resize(mTexture.size());
+ if (mTimerQuery == 0)
+ {
+ glGenQueries(1, &mSamplesQuery);
+ glGenQueries(1, &mTimerQuery);
+ glGenQueries(1, &mPrimitivesQuery);
+ }
- U32 cur_active = gGL.getCurrentTexUnitIndex();
+ glBeginQuery(GL_TIME_ELAPSED, mTimerQuery);
- for (U32 i = 0; i < mTexture.size(); ++i)
+ if (!for_runtime)
{
- GLint idx = mTexture[i];
+ glBeginQuery(GL_SAMPLES_PASSED, mSamplesQuery);
+ glBeginQuery(GL_PRIMITIVES_GENERATED, mPrimitivesQuery);
+ }
+ }
+}
- if (idx >= 0)
+bool LLGLSLShader::readProfileQuery(bool for_runtime, bool force_read)
+{
+ if (sProfileEnabled || for_runtime)
+ {
+ if (!mProfilePending)
+ {
+ glEndQuery(GL_TIME_ELAPSED);
+ if (!for_runtime)
{
- gGL.getTexUnit(idx)->activate();
-
- U32 mag = 0xFFFFFFFF;
- U32 min = 0xFFFFFFFF;
-
- U32 type = LLTexUnit::getInternalType(gGL.getTexUnit(idx)->getCurrType());
+ glEndQuery(GL_SAMPLES_PASSED);
+ glEndQuery(GL_PRIMITIVES_GENERATED);
+ }
+ mProfilePending = for_runtime;
+ }
- glGetTexParameteriv(type, GL_TEXTURE_MAG_FILTER, (GLint*) &mag);
- glGetTexParameteriv(type, GL_TEXTURE_MIN_FILTER, (GLint*) &min);
+ if (mProfilePending && for_runtime && !force_read)
+ {
+ GLuint64 result = 0;
+ glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT_AVAILABLE, &result);
- mTextureMagFilter[i] = mag;
- mTextureMinFilter[i] = min;
+ if (result != GL_TRUE)
+ {
+ return false;
}
}
- gGL.getTexUnit(cur_active)->activate();
- }
-
+ GLuint64 time_elapsed = 0;
+ glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT, &time_elapsed);
+ mTimeElapsed += time_elapsed;
+ mProfilePending = false;
- glBeginQueryARB(GL_SAMPLES_PASSED, mSamplesQuery);
- glBeginQueryARB(GL_TIME_ELAPSED, mTimerQuery);
-#endif
-}
+ if (!for_runtime)
+ {
+ GLuint64 samples_passed = 0;
+ glGetQueryObjectui64v(mSamplesQuery, GL_QUERY_RESULT, &samples_passed);
-void LLGLSLShader::readProfileQuery(U32 count, U32 mode)
-{
-#if !LL_DARWIN
- glEndQueryARB(GL_TIME_ELAPSED);
- glEndQueryARB(GL_SAMPLES_PASSED);
-
- GLuint64 time_elapsed = 0;
- glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT, &time_elapsed);
+ U64 primitives_generated = 0;
+ glGetQueryObjectui64v(mPrimitivesQuery, GL_QUERY_RESULT, &primitives_generated);
+ sTotalTimeElapsed += time_elapsed;
- GLuint64 samples_passed = 0;
- glGetQueryObjectui64v(mSamplesQuery, GL_QUERY_RESULT, &samples_passed);
+ sTotalSamplesDrawn += samples_passed;
+ mSamplesDrawn += samples_passed;
- sTotalTimeElapsed += time_elapsed;
- mTimeElapsed += time_elapsed;
+ U32 tri_count = (U32)primitives_generated / 3;
- sTotalSamplesDrawn += samples_passed;
- mSamplesDrawn += samples_passed;
+ mTrianglesDrawn += tri_count;
+ sTotalTrianglesDrawn += tri_count;
- U32 tri_count = 0;
- switch (mode)
- {
- case LLRender::TRIANGLES: tri_count = count/3; break;
- case LLRender::TRIANGLE_FAN: tri_count = count-2; break;
- case LLRender::TRIANGLE_STRIP: tri_count = count-2; break;
- default: tri_count = count; break; //points lines etc just use primitive count
+ sTotalBinds++;
+ mBinds++;
+ }
}
- mTrianglesDrawn += tri_count;
- sTotalTrianglesDrawn += tri_count;
-
- sTotalDrawCalls++;
- mDrawCalls++;
-#endif
+ return true;
}
LLGLSLShader::LLGLSLShader()
- : mProgramObject(0),
- mAttributeMask(0),
- mTotalUniformSize(0),
- mActiveTextureChannels(0),
- mShaderLevel(0),
- mShaderGroup(SG_DEFAULT),
- mUniformsDirty(FALSE),
- mTimerQuery(0),
- mSamplesQuery(0)
-
+ : mProgramObject(0),
+ mAttributeMask(0),
+ mTotalUniformSize(0),
+ mActiveTextureChannels(0),
+ mShaderLevel(0),
+ mShaderGroup(SG_DEFAULT),
+ mFeatures(),
+ mUniformsDirty(FALSE),
+ mTimerQuery(0),
+ mSamplesQuery(0),
+ mPrimitivesQuery(0)
{
-
+
}
LLGLSLShader::~LLGLSLShader()
@@ -332,6 +325,7 @@ void LLGLSLShader::unload()
{
mShaderFiles.clear();
mDefines.clear();
+ mFeatures = LLShaderFeatures();
unloadInternal();
}
@@ -347,30 +341,37 @@ void LLGLSLShader::unloadInternal()
if (mProgramObject)
{
- GLhandleARB obj[1024];
- GLsizei count;
- glGetAttachedObjectsARB(mProgramObject, 1024, &count, obj);
+ GLuint obj[1024];
+ GLsizei count = 0;
+ glGetAttachedShaders(mProgramObject, 1024, &count, obj);
+
+ for (GLsizei i = 0; i < count; i++)
+ {
+ glDetachShader(mProgramObject, obj[i]);
+ }
for (GLsizei i = 0; i < count; i++)
{
- glDetachObjectARB(mProgramObject, obj[i]);
- glDeleteObjectARB(obj[i]);
+ if (glIsShader(obj[i]))
+ {
+ glDeleteShader(obj[i]);
+ }
}
- glDeleteObjectARB(mProgramObject);
+ glDeleteProgram(mProgramObject);
mProgramObject = 0;
}
if (mTimerQuery)
{
- glDeleteQueriesARB(1, &mTimerQuery);
+ glDeleteQueries(1, &mTimerQuery);
mTimerQuery = 0;
}
if (mSamplesQuery)
{
- glDeleteQueriesARB(1, &mSamplesQuery);
+ glDeleteQueries(1, &mSamplesQuery);
mSamplesQuery = 0;
}
@@ -380,10 +381,10 @@ 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(std::vector<LLStaticHashedString>* attributes,
+ std::vector<LLStaticHashedString>* uniforms,
+ U32 varying_count,
+ const char** varyings)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
@@ -400,8 +401,15 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
llassert_always(!mShaderFiles.empty());
+#if LL_DARWIN
+ // work-around missing mix(vec3,vec3,bvec3)
+ mDefines["OLD_SELECT"] = "1";
+#endif
+
+ mShaderHash = hash();
+
// Create program
- mProgramObject = glCreateProgramObjectARB();
+ mProgramObject = glCreateProgram();
if (mProgramObject == 0)
{
// Shouldn't happen if shader related extensions, like ARB_vertex_shader, exist.
@@ -411,51 +419,38 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
}
BOOL success = TRUE;
-
-#if LL_DARWIN
- // work-around missing mix(vec3,vec3,bvec3)
- mDefines["OLD_SELECT"] = "1";
-#endif
-
+
+ mUsingBinaryProgram = LLShaderMgr::instance()->loadCachedProgramBinary(this);
+
+ if (!mUsingBinaryProgram)
+ {
#if DEBUG_SHADER_INCLUDES
- fprintf(stderr, "--- %s ---\n", mName.c_str());
+ fprintf(stderr, "--- %s ---\n", mName.c_str());
#endif // DEBUG_SHADER_INCLUDES
- //compile new source
- vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin();
- for ( ; fileIter != mShaderFiles.end(); fileIter++ )
- {
- GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, &mDefines, mFeatures.mIndexedTextureChannels);
- LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL;
- if (shaderhandle)
- {
- attachObject(shaderhandle);
- }
- else
- {
- success = FALSE;
- }
+ //compile new source
+ vector< pair<string, GLenum> >::iterator fileIter = mShaderFiles.begin();
+ for (; fileIter != mShaderFiles.end(); fileIter++)
+ {
+ GLuint shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, &mDefines, mFeatures.mIndexedTextureChannels);
+ LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL;
+ if (shaderhandle)
+ {
+ attachObject(shaderhandle);
+ }
+ else
+ {
+ success = FALSE;
+ }
+ }
}
// Attach existing objects
if (!LLShaderMgr::instance()->attachShaderFeatures(this))
{
+ unloadInternal();
return FALSE;
}
-
- if (gGLManager.mGLSLVersionMajor < 2 && gGLManager.mGLSLVersionMinor < 3)
- { //indexed texture rendering requires GLSL 1.3 or later
- //attachShaderFeatures may have set the number of indexed texture channels, so set to 1 again
- mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1);
- }
-
-#ifdef GL_INTERLEAVED_ATTRIBS
- if (varying_count > 0 && varyings)
- {
- glTransformFeedbackVaryings(mProgramObject, varying_count, varyings, GL_INTERLEAVED_ATTRIBS);
- }
-#endif
-
// Map attributes and uniforms
if (success)
{
@@ -465,7 +460,7 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
{
success = mapUniforms(uniforms);
}
- if( !success )
+ if (!success)
{
LL_SHADER_LOADING_WARNS() << "Failed to link shader: " << mName << LL_ENDL;
@@ -474,7 +469,12 @@ 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(attributes, uniforms);
+ }
+ else
+ {
+ // Give up and unload shader.
+ unloadInternal();
}
}
else if (mFeatures.mIndexedTextureChannels > 0)
@@ -501,26 +501,30 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
unbind();
}
+#ifdef LL_PROFILER_ENABLE_RENDER_DOC
+ setLabel(mName.c_str());
+#endif
+
return success;
}
#if DEBUG_SHADER_INCLUDES
-void dumpAttachObject( const char *func_name, GLhandleARB program_object, const std::string &object_path )
+void dumpAttachObject(const char* func_name, GLuint program_object, const std::string& object_path)
{
- GLcharARB* info_log;
+ GLchar* info_log;
GLint info_len_expect = 0;
GLint info_len_actual = 0;
- glGetObjectParameterivARB(program_object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_len_expect);
+ glGetShaderiv(program_object, GL_INFO_LOG_LENGTH, , &info_len_expect);
fprintf(stderr, " * %-20s(), log size: %d, %s\n", func_name, info_len_expect, object_path.c_str());
if (info_len_expect > 0)
{
fprintf(stderr, " ========== %s() ========== \n", func_name);
- info_log = new GLcharARB [ info_len_expect ];
- glGetInfoLogARB(program_object, info_len_expect, &info_len_actual, info_log);
- fprintf(stderr, "%s\n", info_log);
- delete [] info_log;
+ info_log = new GLchar[info_len_expect];
+ glGetProgramInfoLog(program_object, info_len_expect, &info_len_actual, info_log);
+ fprintf(stderr, "%s\n", info_log);
+ delete[] info_log;
}
}
#endif // DEBUG_SHADER_INCLUDES
@@ -530,7 +534,7 @@ BOOL LLGLSLShader::attachVertexObject(std::string object_path)
if (LLShaderMgr::instance()->mVertexShaderObjects.count(object_path) > 0)
{
stop_glerror();
- glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mVertexShaderObjects[object_path]);
+ glAttachShader(mProgramObject, LLShaderMgr::instance()->mVertexShaderObjects[object_path]);
#if DEBUG_SHADER_INCLUDES
dumpAttachObject("attachVertexObject", mProgramObject, object_path);
#endif // DEBUG_SHADER_INCLUDES
@@ -546,10 +550,13 @@ BOOL LLGLSLShader::attachVertexObject(std::string object_path)
BOOL LLGLSLShader::attachFragmentObject(std::string object_path)
{
+ if(mUsingBinaryProgram)
+ return TRUE;
+
if (LLShaderMgr::instance()->mFragmentShaderObjects.count(object_path) > 0)
{
stop_glerror();
- glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mFragmentShaderObjects[object_path]);
+ glAttachShader(mProgramObject, LLShaderMgr::instance()->mFragmentShaderObjects[object_path]);
#if DEBUG_SHADER_INCLUDES
dumpAttachObject("attachFragmentObject", mProgramObject, object_path);
#endif // DEBUG_SHADER_INCLUDES
@@ -563,12 +570,15 @@ BOOL LLGLSLShader::attachFragmentObject(std::string object_path)
}
}
-void LLGLSLShader::attachObject(GLhandleARB object)
+void LLGLSLShader::attachObject(GLuint object)
{
+ if(mUsingBinaryProgram)
+ return;
+
if (object != 0)
{
stop_glerror();
- glAttachObjectARB(mProgramObject, object);
+ glAttachShader(mProgramObject, object);
#if DEBUG_SHADER_INCLUDES
std::string object_path("???");
dumpAttachObject("attachObject", mProgramObject, object_path);
@@ -581,27 +591,34 @@ void LLGLSLShader::attachObject(GLhandleARB object)
}
}
-void LLGLSLShader::attachObjects(GLhandleARB* objects, S32 count)
+void LLGLSLShader::attachObjects(GLuint* objects, S32 count)
{
+ if(mUsingBinaryProgram)
+ return;
+
for (S32 i = 0; i < count; i++)
{
attachObject(objects[i]);
}
}
-BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attributes)
+BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString>* attributes)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
- //before linking, make sure reserved attributes always have consistent locations
- for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++)
- {
- const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str();
- glBindAttribLocationARB(mProgramObject, i, (const GLcharARB *) name);
- }
-
- //link the program
- BOOL res = link();
+ BOOL res = TRUE;
+ if (!mUsingBinaryProgram)
+ {
+ //before linking, make sure reserved attributes always have consistent locations
+ for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++)
+ {
+ const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str();
+ glBindAttribLocation(mProgramObject, i, (const GLchar*)name);
+ }
+
+ //link the program
+ res = link();
+ }
mAttribute.clear();
U32 numAttributes = (attributes == NULL) ? 0 : attributes->size();
@@ -610,7 +627,7 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attri
#else
mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, -1);
#endif
-
+
if (res)
{ //read back channel locations
@@ -620,7 +637,7 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attri
for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++)
{
const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str();
- S32 index = glGetAttribLocationARB(mProgramObject, (const GLcharARB *)name);
+ S32 index = glGetAttribLocation(mProgramObject, (const GLchar*)name);
if (index != -1)
{
#if LL_RELEASE_WITH_DEBUG_INFO
@@ -637,7 +654,7 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attri
for (U32 i = 0; i < numAttributes; i++)
{
const char* name = (*attributes)[i].String().c_str();
- S32 index = glGetAttribLocationARB(mProgramObject, name);
+ S32 index = glGetAttribLocation(mProgramObject, name);
if (index != -1)
{
mAttribute[LLShaderMgr::instance()->mReservedAttribs.size() + i] = index;
@@ -648,11 +665,11 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attri
return TRUE;
}
-
+
return FALSE;
}
-void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> * uniforms)
+void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString>* uniforms)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
@@ -668,52 +685,50 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> *
name[0] = 0;
- glGetActiveUniformARB(mProgramObject, index, 1024, &length, &size, &type, (GLcharARB *)name);
-#if !LL_DARWIN
+ glGetActiveUniform(mProgramObject, index, 1024, &length, &size, &type, (GLchar*)name);
if (size > 0)
{
- switch(type)
- {
- case GL_FLOAT_VEC2: size *= 2; break;
- case GL_FLOAT_VEC3: size *= 3; break;
- case GL_FLOAT_VEC4: size *= 4; break;
- case GL_DOUBLE: size *= 2; break;
- case GL_DOUBLE_VEC2: size *= 2; break;
- case GL_DOUBLE_VEC3: size *= 6; break;
- case GL_DOUBLE_VEC4: size *= 8; break;
- case GL_INT_VEC2: size *= 2; break;
- case GL_INT_VEC3: size *= 3; break;
- case GL_INT_VEC4: size *= 4; break;
- case GL_UNSIGNED_INT_VEC2: size *= 2; break;
- case GL_UNSIGNED_INT_VEC3: size *= 3; break;
- case GL_UNSIGNED_INT_VEC4: size *= 4; break;
- case GL_BOOL_VEC2: size *= 2; break;
- case GL_BOOL_VEC3: size *= 3; break;
- case GL_BOOL_VEC4: size *= 4; break;
- case GL_FLOAT_MAT2: size *= 4; break;
- case GL_FLOAT_MAT3: size *= 9; break;
- case GL_FLOAT_MAT4: size *= 16; break;
- case GL_FLOAT_MAT2x3: size *= 6; break;
- case GL_FLOAT_MAT2x4: size *= 8; break;
- case GL_FLOAT_MAT3x2: size *= 6; break;
- case GL_FLOAT_MAT3x4: size *= 12; break;
- case GL_FLOAT_MAT4x2: size *= 8; break;
- case GL_FLOAT_MAT4x3: size *= 12; break;
- case GL_DOUBLE_MAT2: size *= 8; break;
- case GL_DOUBLE_MAT3: size *= 18; break;
- case GL_DOUBLE_MAT4: size *= 32; break;
- case GL_DOUBLE_MAT2x3: size *= 12; break;
- case GL_DOUBLE_MAT2x4: size *= 16; break;
- case GL_DOUBLE_MAT3x2: size *= 12; break;
- case GL_DOUBLE_MAT3x4: size *= 24; break;
- case GL_DOUBLE_MAT4x2: size *= 16; break;
- case GL_DOUBLE_MAT4x3: size *= 24; break;
+ switch (type)
+ {
+ case GL_FLOAT_VEC2: size *= 2; break;
+ case GL_FLOAT_VEC3: size *= 3; break;
+ case GL_FLOAT_VEC4: size *= 4; break;
+ case GL_DOUBLE: size *= 2; break;
+ case GL_DOUBLE_VEC2: size *= 2; break;
+ case GL_DOUBLE_VEC3: size *= 6; break;
+ case GL_DOUBLE_VEC4: size *= 8; break;
+ case GL_INT_VEC2: size *= 2; break;
+ case GL_INT_VEC3: size *= 3; break;
+ case GL_INT_VEC4: size *= 4; break;
+ case GL_UNSIGNED_INT_VEC2: size *= 2; break;
+ case GL_UNSIGNED_INT_VEC3: size *= 3; break;
+ case GL_UNSIGNED_INT_VEC4: size *= 4; break;
+ case GL_BOOL_VEC2: size *= 2; break;
+ case GL_BOOL_VEC3: size *= 3; break;
+ case GL_BOOL_VEC4: size *= 4; break;
+ case GL_FLOAT_MAT2: size *= 4; break;
+ case GL_FLOAT_MAT3: size *= 9; break;
+ case GL_FLOAT_MAT4: size *= 16; break;
+ case GL_FLOAT_MAT2x3: size *= 6; break;
+ case GL_FLOAT_MAT2x4: size *= 8; break;
+ case GL_FLOAT_MAT3x2: size *= 6; break;
+ case GL_FLOAT_MAT3x4: size *= 12; break;
+ case GL_FLOAT_MAT4x2: size *= 8; break;
+ case GL_FLOAT_MAT4x3: size *= 12; break;
+ case GL_DOUBLE_MAT2: size *= 8; break;
+ case GL_DOUBLE_MAT3: size *= 18; break;
+ case GL_DOUBLE_MAT4: size *= 32; break;
+ case GL_DOUBLE_MAT2x3: size *= 12; break;
+ case GL_DOUBLE_MAT2x4: size *= 16; break;
+ case GL_DOUBLE_MAT3x2: size *= 12; break;
+ case GL_DOUBLE_MAT3x4: size *= 24; break;
+ case GL_DOUBLE_MAT4x2: size *= 16; break;
+ case GL_DOUBLE_MAT4x3: size *= 24; break;
}
mTotalUniformSize += size;
}
-#endif
- S32 location = glGetUniformLocationARB(mProgramObject, name);
+ S32 location = glGetUniformLocation(mProgramObject, name);
if (location != -1)
{
//chop off "[0]" so we can always access the first element
@@ -725,20 +740,19 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> *
}
LLStaticHashedString hashedName(name);
- mUniformNameMap[location] = name;
mUniformMap[hashedName] = location;
LL_DEBUGS("ShaderUniform") << "Uniform " << name << " is at location " << location << LL_ENDL;
-
+
//find the index of this uniform
- for (S32 i = 0; i < (S32) LLShaderMgr::instance()->mReservedUniforms.size(); i++)
+ for (S32 i = 0; i < (S32)LLShaderMgr::instance()->mReservedUniforms.size(); i++)
{
- if ( (mUniform[i] == -1)
+ if ((mUniform[i] == -1)
&& (LLShaderMgr::instance()->mReservedUniforms[i] == name))
{
//found it
mUniform[i] = location;
- mTexture[i] = mapUniformTextureChannel(location, type);
+ mTexture[i] = mapUniformTextureChannel(location, type, size);
return;
}
}
@@ -747,12 +761,12 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> *
{
for (U32 i = 0; i < uniforms->size(); i++)
{
- if ( (mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] == -1)
+ if ((mUniform[i + LLShaderMgr::instance()->mReservedUniforms.size()] == -1)
&& ((*uniforms)[i].String() == name))
{
//found it
- mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] = location;
- mTexture[i+LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type);
+ mUniform[i + LLShaderMgr::instance()->mReservedUniforms.size()] = location;
+ mTexture[i + LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type, size);
return;
}
}
@@ -770,167 +784,220 @@ void LLGLSLShader::addPermutation(std::string name, std::string value)
mDefines[name] = value;
}
+void LLGLSLShader::addConstant(const LLGLSLShader::eShaderConsts shader_const)
+{
+ addPermutation(gShaderConstsKey[shader_const], gShaderConstsVal[shader_const]);
+}
+
void LLGLSLShader::removePermutation(std::string name)
{
- mDefines[name].erase();
+ mDefines.erase(name);
}
-GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
+GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type, GLint size)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
- if ((type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB) ||
- type == GL_SAMPLER_2D_MULTISAMPLE)
+ if ((type >= GL_SAMPLER_1D && type <= GL_SAMPLER_2D_RECT_SHADOW) ||
+ type == GL_SAMPLER_2D_MULTISAMPLE ||
+ type == GL_SAMPLER_CUBE_MAP_ARRAY)
{ //this here is a texture
- glUniform1iARB(location, mActiveTextureChannels);
- LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL;
- return mActiveTextureChannels++;
+ GLint ret = mActiveTextureChannels;
+ 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);
+ 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(const vector<LLStaticHashedString>* uniforms)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
BOOL res = TRUE;
- mTotalUniformSize = 0;
- mActiveTextureChannels = 0;
- mUniform.clear();
- mUniformMap.clear();
- mUniformNameMap.clear();
- mTexture.clear();
- mValue.clear();
- //initialize arrays
- U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size();
- mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1);
- mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1);
+ mTotalUniformSize = 0;
+ mActiveTextureChannels = 0;
+ mUniform.clear();
+ mUniformMap.clear();
+ mTexture.clear();
+ mValue.clear();
+ //initialize arrays
+ U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size();
+ mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1);
+ mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1);
- bind();
+ bind();
- //get the number of active uniforms
- GLint activeCount;
- glGetObjectParameterivARB(mProgramObject, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &activeCount);
+ //get the number of active uniforms
+ GLint activeCount;
+ glGetProgramiv(mProgramObject, GL_ACTIVE_UNIFORMS, &activeCount);
- //........................................................................................................................................
- //........................................................................................
+ //........................................................................................................................................
+ //........................................................................................
- /*
- EXPLANATION:
- This is part of code is temporary because as the final result the mapUniform() should be rewrited.
- But it's a huge a volume of work which is need to be a more carefully performed for avoid possible
- regression's (i.e. it should be formalized a separate ticket in JIRA).
+ /*
+ EXPLANATION:
+ This is part of code is temporary because as the final result the mapUniform() should be rewrited.
+ But it's a huge a volume of work which is need to be a more carefully performed for avoid possible
+ regression's (i.e. it should be formalized a separate ticket in JIRA).
- RESON:
- The reason of this code is that SL engine is very sensitive to fact that "diffuseMap" should be appear
- first as uniform parameter which is should get 0-"texture channel" index (see mapUniformTextureChannel() and mActiveTextureChannels)
- it influence to which is texture matrix will be updated during rendering.
+ RESON:
+ The reason of this code is that SL engine is very sensitive to fact that "diffuseMap" should be appear
+ first as uniform parameter which is should get 0-"texture channel" index (see mapUniformTextureChannel() and mActiveTextureChannels)
+ it influence to which is texture matrix will be updated during rendering.
- But, order of indexe's of uniform variables is not defined and GLSL compiler can change it as want
- , even if the "diffuseMap" will be appear and use first in shader code.
+ But, order of indexe's of uniform variables is not defined and GLSL compiler can change it as want
+ , even if the "diffuseMap" will be appear and use first in shader code.
- As example where this situation appear see: "Deferred Material Shader 28/29/30/31"
- And tickets: MAINT-4165, MAINT-4839, MAINT-3568, MAINT-6437
- */
+ As example where this situation appear see: "Deferred Material Shader 28/29/30/31"
+ And tickets: MAINT-4165, MAINT-4839, MAINT-3568, MAINT-6437
+ --- davep TODO -- pretty sure the entire block here is superstitious and that the uniform index has nothing to do with the texture channel
+ texture channel should follow the uniform VALUE
+ */
- S32 diffuseMap = glGetUniformLocationARB(mProgramObject, "diffuseMap");
- S32 specularMap = glGetUniformLocationARB(mProgramObject, "specularMap");
- S32 bumpMap = glGetUniformLocationARB(mProgramObject, "bumpMap");
- S32 altDiffuseMap = glGetUniformLocationARB(mProgramObject, "altDiffuseMap");
- S32 environmentMap = glGetUniformLocationARB(mProgramObject, "environmentMap");
- std::set<S32> skip_index;
+ S32 diffuseMap = glGetUniformLocation(mProgramObject, "diffuseMap");
+ S32 specularMap = glGetUniformLocation(mProgramObject, "specularMap");
+ S32 bumpMap = glGetUniformLocation(mProgramObject, "bumpMap");
+ S32 altDiffuseMap = glGetUniformLocation(mProgramObject, "altDiffuseMap");
+ S32 environmentMap = glGetUniformLocation(mProgramObject, "environmentMap");
+ S32 reflectionMap = glGetUniformLocation(mProgramObject, "reflectionMap");
- if (-1 != diffuseMap && (-1 != specularMap || -1 != bumpMap || -1 != environmentMap || -1 != altDiffuseMap))
- {
- GLenum type;
- GLsizei length;
- GLint size = -1;
- char name[1024];
+ std::set<S32> skip_index;
- diffuseMap = altDiffuseMap = specularMap = bumpMap = environmentMap = -1;
+ if (-1 != diffuseMap && (-1 != specularMap || -1 != bumpMap || -1 != environmentMap || -1 != altDiffuseMap))
+ {
+ GLenum type;
+ GLsizei length;
+ GLint size = -1;
+ char name[1024];
- for (S32 i = 0; i < activeCount; i++)
- {
- name[0] = '\0';
+ diffuseMap = altDiffuseMap = specularMap = bumpMap = environmentMap = -1;
- glGetActiveUniformARB(mProgramObject, i, 1024, &length, &size, &type, (GLcharARB *)name);
+ for (S32 i = 0; i < activeCount; i++)
+ {
+ name[0] = '\0';
- if (-1 == diffuseMap && std::string(name) == "diffuseMap")
- {
- diffuseMap = i;
- continue;
- }
+ glGetActiveUniform(mProgramObject, i, 1024, &length, &size, &type, (GLchar*)name);
- if (-1 == specularMap && std::string(name) == "specularMap")
- {
- specularMap = i;
- continue;
- }
+ if (-1 == diffuseMap && std::string(name) == "diffuseMap")
+ {
+ diffuseMap = i;
+ continue;
+ }
- if (-1 == bumpMap && std::string(name) == "bumpMap")
- {
- bumpMap = i;
- continue;
- }
+ if (-1 == specularMap && std::string(name) == "specularMap")
+ {
+ specularMap = i;
+ continue;
+ }
- if (-1 == environmentMap && std::string(name) == "environmentMap")
- {
- environmentMap = i;
- continue;
- }
+ if (-1 == bumpMap && std::string(name) == "bumpMap")
+ {
+ bumpMap = i;
+ continue;
+ }
+
+ if (-1 == environmentMap && std::string(name) == "environmentMap")
+ {
+ environmentMap = i;
+ continue;
+ }
+
+ if (-1 == reflectionMap && std::string(name) == "reflectionMap")
+ {
+ reflectionMap = i;
+ continue;
+ }
if (-1 == altDiffuseMap && std::string(name) == "altDiffuseMap")
- {
- altDiffuseMap = i;
- continue;
- }
- }
+ {
+ altDiffuseMap = i;
+ continue;
+ }
+ }
- bool specularDiff = specularMap < diffuseMap && -1 != specularMap;
- bool bumpLessDiff = bumpMap < diffuseMap && -1 != bumpMap;
- bool envLessDiff = environmentMap < diffuseMap && -1 != environmentMap;
+ bool specularDiff = specularMap < diffuseMap && -1 != specularMap;
+ bool bumpLessDiff = bumpMap < diffuseMap && -1 != bumpMap;
+ bool envLessDiff = environmentMap < diffuseMap && -1 != environmentMap;
+ bool refLessDiff = reflectionMap < diffuseMap && -1 != reflectionMap;
- if (specularDiff || bumpLessDiff || envLessDiff)
- {
- mapUniform(diffuseMap, uniforms);
- skip_index.insert(diffuseMap);
+ if (specularDiff || bumpLessDiff || envLessDiff || refLessDiff)
+ {
+ mapUniform(diffuseMap, uniforms);
+ skip_index.insert(diffuseMap);
- if (-1 != specularMap) {
- mapUniform(specularMap, uniforms);
- skip_index.insert(specularMap);
- }
+ if (-1 != specularMap) {
+ mapUniform(specularMap, uniforms);
+ skip_index.insert(specularMap);
+ }
- if (-1 != bumpMap) {
- mapUniform(bumpMap, uniforms);
- skip_index.insert(bumpMap);
- }
+ if (-1 != bumpMap) {
+ mapUniform(bumpMap, uniforms);
+ skip_index.insert(bumpMap);
+ }
- if (-1 != environmentMap) {
- mapUniform(environmentMap, uniforms);
- skip_index.insert(environmentMap);
- }
- }
- }
+ if (-1 != environmentMap) {
+ mapUniform(environmentMap, uniforms);
+ skip_index.insert(environmentMap);
+ }
+
+ if (-1 != reflectionMap) {
+ mapUniform(reflectionMap, uniforms);
+ skip_index.insert(reflectionMap);
+ }
+ }
+ }
- //........................................................................................
+ //........................................................................................
- for (S32 i = 0; i < activeCount; i++)
- {
- //........................................................................................
- if (skip_index.end() != skip_index.find(i)) continue;
- //........................................................................................
+ for (S32 i = 0; i < activeCount; i++)
+ {
+ //........................................................................................
+ if (skip_index.end() != skip_index.find(i)) continue;
+ //........................................................................................
- mapUniform(i, uniforms);
- }
- //........................................................................................................................................
+ mapUniform(i, uniforms);
+ }
+ //........................................................................................................................................
- unbind();
+ 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");
+ if (UBOBlockIndex != GL_INVALID_INDEX)
+ {
+ //Set this index to a binding index
+ glUniformBlockBinding(mProgramObject, UBOBlockIndex, BLOCKBINDING);
+ }
+ }
+ unbind();
- LL_DEBUGS("ShaderUniform") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL;
- return res;
+ LL_DEBUGS("ShaderUniform") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL;
+ return res;
}
@@ -945,6 +1012,11 @@ BOOL LLGLSLShader::link(BOOL suppress_errors)
LLShaderMgr::instance()->dumpObjectLog(mProgramObject, !success, mName);
}
+ if (success)
+ {
+ LLShaderMgr::instance()->saveCachedProgramBinary(this);
+ }
+
return success;
}
@@ -952,14 +1024,22 @@ void LLGLSLShader::bind()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(mProgramObject != 0);
+
gGL.flush();
if (sCurBoundShader != mProgramObject) // Don't re-bind current shader
{
+ if (sCurBoundShaderPtr)
+ {
+ sCurBoundShaderPtr->readProfileQuery();
+ }
LLVertexBuffer::unbind();
- glUseProgramObjectARB(mProgramObject);
+ glUseProgram(mProgramObject);
sCurBoundShader = mProgramObject;
sCurBoundShaderPtr = this;
+ placeProfileQuery();
+ LLVertexBuffer::setupClientArrays(mAttributeMask);
}
if (mUniformsDirty)
@@ -982,40 +1062,33 @@ void LLGLSLShader::bind(bool rigged)
}
}
-void LLGLSLShader::unbind()
+void LLGLSLShader::unbind(void)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
-
gGL.flush();
- stop_glerror();
LLVertexBuffer::unbind();
- glUseProgramObjectARB(0);
- sCurBoundShader = 0;
- sCurBoundShaderPtr = NULL;
- stop_glerror();
-}
-void LLGLSLShader::bindNoShader(void)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ if (sCurBoundShaderPtr)
+ {
+ sCurBoundShaderPtr->readProfileQuery();
+ }
- LLVertexBuffer::unbind();
- glUseProgramObjectARB(0);
+ glUseProgram(0);
sCurBoundShader = 0;
sCurBoundShaderPtr = NULL;
}
-S32 LLGLSLShader::bindTexture(const std::string &uniform, LLTexture *texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace)
+S32 LLGLSLShader::bindTexture(const std::string& uniform, LLTexture* texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
S32 channel = 0;
channel = getUniformLocation(uniform);
-
+
return bindTexture(channel, texture, mode, colorspace);
}
-S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace)
+S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
@@ -1024,25 +1097,62 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextu
LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
return -1;
}
-
+
uniform = mTexture[uniform];
-
+
if (uniform > -1)
{
gGL.getTexUnit(uniform)->bindFast(texture);
gGL.getTexUnit(uniform)->setTextureColorSpace(colorspace);
}
-
+
return uniform;
}
-S32 LLGLSLShader::unbindTexture(const std::string &uniform, LLTexUnit::eTextureType mode)
+S32 LLGLSLShader::bindTexture(S32 uniform, LLRenderTarget* texture, bool depth, LLTexUnit::eTextureFilterOptions mode, U32 index)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+
+ if (uniform < 0 || uniform >= (S32)mTexture.size())
+ {
+ return -1;
+ }
+
+ uniform = getTextureChannel(uniform);
+
+ if (uniform > -1)
+ {
+ if (depth) {
+ gGL.getTexUnit(uniform)->bind(texture, true);
+ }
+ else {
+ bool has_mips = mode == LLTexUnit::TFO_TRILINEAR || mode == LLTexUnit::TFO_ANISOTROPIC;
+ gGL.getTexUnit(uniform)->bindManual(texture->getUsage(), texture->getTexture(index), has_mips);
+ }
+
+ gGL.getTexUnit(uniform)->setTextureFilteringOption(mode);
+ }
+
+ return uniform;
+}
+
+S32 LLGLSLShader::bindTexture(const std::string& uniform, LLRenderTarget* texture, bool depth, LLTexUnit::eTextureFilterOptions mode)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
S32 channel = 0;
channel = getUniformLocation(uniform);
-
+
+ return bindTexture(channel, texture, depth, mode);
+}
+
+S32 LLGLSLShader::unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+
+ S32 channel = 0;
+ channel = getUniformLocation(uniform);
+
return unbindTexture(channel);
}
@@ -1055,17 +1165,22 @@ S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode)
LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
return -1;
}
-
+
uniform = mTexture[uniform];
-
+
if (uniform > -1)
{
gGL.getTexUnit(uniform)->unbindFast(mode);
}
-
+
return uniform;
}
+S32 LLGLSLShader::getTextureChannel(S32 uniform) const
+{
+ return mTexture[uniform];
+}
+
S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
@@ -1116,9 +1231,10 @@ S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTe
void LLGLSLShader::uniform1i(U32 index, GLint x)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1130,8 +1246,8 @@ void LLGLSLShader::uniform1i(U32 index, GLint x)
const auto& iter = mValue.find(mUniform[index]);
if (iter == mValue.end() || iter->second.mV[0] != x)
{
- glUniform1iARB(mUniform[index], x);
- mValue[mUniform[index]] = LLVector4(x,0.f,0.f,0.f);
+ glUniform1i(mUniform[index], x);
+ mValue[mUniform[index]] = LLVector4(x, 0.f, 0.f, 0.f);
}
}
}
@@ -1139,9 +1255,11 @@ void LLGLSLShader::uniform1i(U32 index, GLint x)
void LLGLSLShader::uniform1f(U32 index, GLfloat x)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1153,17 +1271,30 @@ void LLGLSLShader::uniform1f(U32 index, GLfloat x)
const auto& iter = mValue.find(mUniform[index]);
if (iter == mValue.end() || iter->second.mV[0] != x)
{
- glUniform1fARB(mUniform[index], x);
- mValue[mUniform[index]] = LLVector4(x,0.f,0.f,0.f);
+ glUniform1f(mUniform[index], x);
+ mValue[mUniform[index]] = LLVector4(x, 0.f, 0.f, 0.f);
}
}
}
}
+void LLGLSLShader::fastUniform1f(U32 index, GLfloat x)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+ llassert(mProgramObject);
+ llassert(mUniform.size() <= index);
+ llassert(mUniform[index] >= 0);
+ glUniform1f(mUniform[index], x);
+}
+
void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1173,10 +1304,10 @@ void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y)
if (mUniform[index] >= 0)
{
const auto& iter = mValue.find(mUniform[index]);
- LLVector4 vec(x,y,0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec))
+ LLVector4 vec(x, y, 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec))
{
- glUniform2fARB(mUniform[index], x, y);
+ glUniform2f(mUniform[index], x, y);
mValue[mUniform[index]] = vec;
}
}
@@ -1185,8 +1316,11 @@ void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y)
void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1196,10 +1330,10 @@ void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z)
if (mUniform[index] >= 0)
{
const auto& iter = mValue.find(mUniform[index]);
- LLVector4 vec(x,y,z,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec))
+ LLVector4 vec(x, y, z, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec))
{
- glUniform3fARB(mUniform[index], x, y, z);
+ glUniform3f(mUniform[index], x, y, z);
mValue[mUniform[index]] = vec;
}
}
@@ -1208,8 +1342,11 @@ void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z)
void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1219,10 +1356,10 @@ void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat
if (mUniform[index] >= 0)
{
const auto& iter = mValue.find(mUniform[index]);
- LLVector4 vec(x,y,z,w);
- if (iter == mValue.end() || shouldChange(iter->second,vec))
+ LLVector4 vec(x, y, z, w);
+ if (iter == mValue.end() || shouldChange(iter->second, vec))
{
- glUniform4fARB(mUniform[index], x, y, z, w);
+ glUniform4f(mUniform[index], x, y, z, w);
mValue[mUniform[index]] = vec;
}
}
@@ -1231,8 +1368,37 @@ void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat
void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
+ if (mProgramObject)
+ {
+ if (mUniform.size() <= index)
+ {
+ LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
+ return;
+ }
+
+ if (mUniform[index] >= 0)
+ {
+ const auto& iter = mValue.find(mUniform[index]);
+ LLVector4 vec(v[0], 0.f, 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
+ {
+ glUniform1iv(mUniform[index], count, v);
+ mValue[mUniform[index]] = vec;
+ }
+ }
+ }
+}
+
+void LLGLSLShader::uniform4iv(U32 index, U32 count, const GLint* v)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1242,20 +1408,24 @@ void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v)
if (mUniform[index] >= 0)
{
const auto& iter = mValue.find(mUniform[index]);
- LLVector4 vec(v[0],0.f,0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ LLVector4 vec(v[0], v[1], v[2], v[3]);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
- glUniform1ivARB(mUniform[index], count, v);
+ glUniform1iv(mUniform[index], count, v);
mValue[mUniform[index]] = vec;
}
}
}
}
+
void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1265,10 +1435,10 @@ void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v)
if (mUniform[index] >= 0)
{
const auto& iter = mValue.find(mUniform[index]);
- LLVector4 vec(v[0],0.f,0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ LLVector4 vec(v[0], 0.f, 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
- glUniform1fvARB(mUniform[index], count, v);
+ glUniform1fv(mUniform[index], count, v);
mValue[mUniform[index]] = vec;
}
}
@@ -1277,8 +1447,11 @@ void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v)
void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1288,10 +1461,10 @@ void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v)
if (mUniform[index] >= 0)
{
const auto& iter = mValue.find(mUniform[index]);
- LLVector4 vec(v[0],v[1],0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ LLVector4 vec(v[0], v[1], 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
- glUniform2fvARB(mUniform[index], count, v);
+ glUniform2fv(mUniform[index], count, v);
mValue[mUniform[index]] = vec;
}
}
@@ -1300,8 +1473,11 @@ void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v)
void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1311,10 +1487,10 @@ void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v)
if (mUniform[index] >= 0)
{
const auto& iter = mValue.find(mUniform[index]);
- LLVector4 vec(v[0],v[1],v[2],0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ LLVector4 vec(v[0], v[1], v[2], 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
- glUniform3fvARB(mUniform[index], count, v);
+ glUniform3fv(mUniform[index], count, v);
mValue[mUniform[index]] = vec;
}
}
@@ -1323,8 +1499,11 @@ void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v)
void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1334,21 +1513,24 @@ void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v)
if (mUniform[index] >= 0)
{
const auto& iter = mValue.find(mUniform[index]);
- LLVector4 vec(v[0],v[1],v[2],v[3]);
- if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ LLVector4 vec(v[0], v[1], v[2], v[3]);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
- glUniform4fvARB(mUniform[index], count, v);
+ glUniform4fv(mUniform[index], count, v);
mValue[mUniform[index]] = vec;
}
}
}
}
-void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v)
+void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1357,15 +1539,18 @@ void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, c
if (mUniform[index] >= 0)
{
- glUniformMatrix2fvARB(mUniform[index], count, transpose, v);
+ glUniformMatrix2fv(mUniform[index], count, transpose, v);
}
}
}
-void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v)
+void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1374,34 +1559,38 @@ void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, c
if (mUniform[index] >= 0)
{
- glUniformMatrix3fvARB(mUniform[index], count, transpose, v);
+ glUniformMatrix3fv(mUniform[index], count, transpose, v);
}
}
}
-void LLGLSLShader::uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v)
+void LLGLSLShader::uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
- if (mProgramObject)
- {
- if (mUniform.size() <= index)
- {
- LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
- return;
- }
+ if (mProgramObject)
+ {
+ if (mUniform.size() <= index)
+ {
+ LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
+ return;
+ }
- if (mUniform[index] >= 0)
- {
- glUniformMatrix3x4fv(mUniform[index], count, transpose, v);
- }
- }
+ if (mUniform[index] >= 0)
+ {
+ glUniformMatrix3x4fv(mUniform[index], count, transpose, v);
+ }
+ }
}
-void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v)
+void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1410,7 +1599,7 @@ void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, c
if (mUniform[index] >= 0)
{
- glUniformMatrix4fvARB(mUniform[index], count, transpose, v);
+ glUniformMatrix4fv(mUniform[index], count, transpose, v);
}
}
}
@@ -1428,7 +1617,7 @@ GLint LLGLSLShader::getUniformLocation(const LLStaticHashedString& uniform)
if (gDebugGL)
{
stop_glerror();
- if (iter->second != glGetUniformLocationARB(mProgramObject, uniform.String().c_str()))
+ if (iter->second != glGetUniformLocation(mProgramObject, uniform.String().c_str()))
{
LL_ERRS() << "Uniform does not match." << LL_ENDL;
}
@@ -1475,15 +1664,52 @@ GLint LLGLSLShader::getAttribLocation(U32 attrib)
void LLGLSLShader::uniform1i(const LLStaticHashedString& uniform, GLint v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ const auto& iter = mValue.find(location);
+ LLVector4 vec(v, 0.f, 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec))
+ {
+ glUniform1i(location, v);
+ mValue[location] = vec;
+ }
+ }
+}
+
+void LLGLSLShader::uniform1iv(const LLStaticHashedString& uniform, U32 count, const GLint* v)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ LLVector4 vec(v[0], 0, 0, 0);
+ const auto& iter = mValue.find(location);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ glUniform1iv(location, count, v);
+ mValue[location] = vec;
+ }
+ }
+}
+
+void LLGLSLShader::uniform4iv(const LLStaticHashedString& uniform, U32 count, const GLint* v)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
-
+
if (location >= 0)
{
+ LLVector4 vec(v[0], v[1], v[2], v[3]);
const auto& iter = mValue.find(location);
- LLVector4 vec(v,0.f,0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec))
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
- glUniform1iARB(location, v);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ glUniform4iv(location, count, v);
mValue[location] = vec;
}
}
@@ -1491,15 +1717,16 @@ void LLGLSLShader::uniform1i(const LLStaticHashedString& uniform, GLint v)
void LLGLSLShader::uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
-
+
if (location >= 0)
{
const auto& iter = mValue.find(location);
- LLVector4 vec(i,j,0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec))
+ LLVector4 vec(i, j, 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec))
{
- glUniform2iARB(location, i, j);
+ glUniform2i(location, i, j);
mValue[location] = vec;
}
}
@@ -1508,15 +1735,16 @@ void LLGLSLShader::uniform2i(const LLStaticHashedString& uniform, GLint i, GLint
void LLGLSLShader::uniform1f(const LLStaticHashedString& uniform, GLfloat v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
-
+
if (location >= 0)
{
const auto& iter = mValue.find(location);
- LLVector4 vec(v,0.f,0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec))
+ LLVector4 vec(v, 0.f, 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec))
{
- glUniform1fARB(location, v);
+ glUniform1f(location, v);
mValue[location] = vec;
}
}
@@ -1524,15 +1752,16 @@ void LLGLSLShader::uniform1f(const LLStaticHashedString& uniform, GLfloat v)
void LLGLSLShader::uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
-
+
if (location >= 0)
{
const auto& iter = mValue.find(location);
- LLVector4 vec(x,y,0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec))
+ LLVector4 vec(x, y, 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec))
{
- glUniform2fARB(location, x,y);
+ glUniform2f(location, x, y);
mValue[location] = vec;
}
}
@@ -1541,15 +1770,16 @@ void LLGLSLShader::uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLf
void LLGLSLShader::uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
-
+
if (location >= 0)
{
const auto& iter = mValue.find(location);
- LLVector4 vec(x,y,z,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec))
+ LLVector4 vec(x, y, z, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec))
{
- glUniform3fARB(location, x,y,z);
+ glUniform3f(location, x, y, z);
mValue[location] = vec;
}
}
@@ -1557,15 +1787,16 @@ void LLGLSLShader::uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLf
void LLGLSLShader::uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
if (location >= 0)
{
const auto& iter = mValue.find(location);
- LLVector4 vec(v[0],0.f,0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ LLVector4 vec(v[0], 0.f, 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
- glUniform1fvARB(location, count, v);
+ glUniform1fv(location, count, v);
mValue[location] = vec;
}
}
@@ -1573,15 +1804,16 @@ void LLGLSLShader::uniform1fv(const LLStaticHashedString& uniform, U32 count, co
void LLGLSLShader::uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
-
+
if (location >= 0)
{
const auto& iter = mValue.find(location);
- LLVector4 vec(v[0],v[1],0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ LLVector4 vec(v[0], v[1], 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
- glUniform2fvARB(location, count, v);
+ glUniform2fv(location, count, v);
mValue[location] = vec;
}
}
@@ -1589,15 +1821,16 @@ void LLGLSLShader::uniform2fv(const LLStaticHashedString& uniform, U32 count, co
void LLGLSLShader::uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
-
+
if (location >= 0)
{
const auto& iter = mValue.find(location);
- LLVector4 vec(v[0],v[1],v[2],0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ LLVector4 vec(v[0], v[1], v[2], 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
- glUniform3fvARB(location, count, v);
+ glUniform3fv(location, count, v);
mValue[location] = vec;
}
}
@@ -1605,16 +1838,17 @@ void LLGLSLShader::uniform3fv(const LLStaticHashedString& uniform, U32 count, co
void LLGLSLShader::uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
if (location >= 0)
{
LLVector4 vec(v);
const auto& iter = mValue.find(location);
- if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
- glUniform4fvARB(location, count, v);
+ glUniform4fv(location, count, v);
mValue[location] = vec;
}
}
@@ -1622,12 +1856,13 @@ void LLGLSLShader::uniform4fv(const LLStaticHashedString& uniform, U32 count, co
void LLGLSLShader::uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
-
+
if (location >= 0)
{
stop_glerror();
- glUniformMatrix4fvARB(location, count, transpose, v);
+ glUniformMatrix4fv(location, count, transpose, v);
stop_glerror();
}
}
@@ -1637,7 +1872,7 @@ void LLGLSLShader::vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GL
{
if (mAttribute[index] > 0)
{
- glVertexAttrib4fARB(mAttribute[index], x, y, z, w);
+ glVertexAttrib4f(mAttribute[index], x, y, z, w);
}
}
@@ -1645,12 +1880,13 @@ void LLGLSLShader::vertexAttrib4fv(U32 index, GLfloat* v)
{
if (mAttribute[index] > 0)
{
- glVertexAttrib4fvARB(mAttribute[index], v);
+ glVertexAttrib4fv(mAttribute[index], v);
}
}
void LLGLSLShader::setMinimumAlpha(F32 minimum)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
gGL.flush();
uniform1f(LLShaderMgr::MINIMUM_ALPHA, minimum);
}
@@ -1678,3 +1914,39 @@ void LLShaderUniforms::apply(LLGLSLShader* shader)
shader->uniform3fv(uniform.mUniform, 1, uniform.mValue.mV);
}
}
+
+LLUUID LLGLSLShader::hash()
+{
+ HBXXH128 hash_obj;
+ hash_obj.update(mName);
+ hash_obj.update(&mShaderGroup, sizeof(mShaderGroup));
+ hash_obj.update(&mShaderLevel, sizeof(mShaderLevel));
+ for (const auto& shdr_pair : mShaderFiles)
+ {
+ hash_obj.update(shdr_pair.first);
+ hash_obj.update(&shdr_pair.second, sizeof(GLenum));
+ }
+ for (const auto& define_pair : mDefines)
+ {
+ hash_obj.update(define_pair.first);
+ hash_obj.update(define_pair.second);
+
+ }
+ for (const auto& define_pair : LLGLSLShader::sGlobalDefines)
+ {
+ hash_obj.update(define_pair.first);
+ hash_obj.update(define_pair.second);
+
+ }
+ hash_obj.update(&mFeatures, sizeof(LLShaderFeatures));
+ hash_obj.update(gGLManager.mGLVendor);
+ hash_obj.update(gGLManager.mGLRenderer);
+ hash_obj.update(gGLManager.mGLVersionString);
+ return hash_obj.digest();
+}
+
+#ifdef LL_PROFILER_ENABLE_RENDER_DOC
+void LLGLSLShader::setLabel(const char* label) {
+ LL_LABEL_OBJECT_GL(GL_PROGRAM, mProgramObject, strlen(label), label);
+}
+#endif
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 85e83dbcb9..b8071248e2 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llglslshader.h
* @brief GLSL shader wrappers
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -35,34 +35,28 @@
class LLShaderFeatures
{
public:
- bool atmosphericHelpers;
- bool calculatesLighting;
- bool calculatesAtmospherics;
- bool hasLighting; // implies no transport (it's possible to have neither though)
- bool isAlphaLighting; // indicates lighting shaders need not be linked in (lighting performed directly in alpha shader to match deferred lighting functions)
- bool isShiny;
- bool isFullbright; // implies no lighting
- bool isSpecular;
- bool hasWaterFog; // implies no gamma
- bool hasTransport; // implies no lighting (it's possible to have neither though)
- bool hasSkinning;
- bool hasObjectSkinning;
- bool hasAtmospherics;
- bool hasGamma;
- bool hasShadows;
- bool hasAmbientOcclusion;
- bool hasSrgb;
- bool encodesNormal;
- bool isDeferred;
- bool hasIndirect;
- S32 mIndexedTextureChannels;
- bool disableTextureIndex;
- bool hasAlphaMask;
- bool attachNothing;
-
- // char numLights;
-
- LLShaderFeatures();
+ S32 mIndexedTextureChannels = 0;
+ bool calculatesLighting = false;
+ bool calculatesAtmospherics = false;
+ bool hasLighting = false; // implies no transport (it's possible to have neither though)
+ bool isAlphaLighting = false; // indicates lighting shaders need not be linked in (lighting performed directly in alpha shader to match deferred lighting functions)
+ bool isSpecular = false;
+ bool hasWaterFog = false; // implies no gamma
+ bool hasTransport = false; // implies no lighting (it's possible to have neither though)
+ bool hasSkinning = false;
+ bool hasObjectSkinning = false;
+ bool hasAtmospherics = false;
+ bool hasGamma = false;
+ bool hasShadows = false;
+ bool hasAmbientOcclusion = false;
+ bool hasSrgb = false;
+ bool encodesNormal = false; // include: shaders\class1\environment\encodeNormF.glsl
+ bool isDeferred = false;
+ bool hasScreenSpaceReflections = false;
+ bool disableTextureIndex = false;
+ bool hasAlphaMask = false;
+ bool hasReflectionProbes = false;
+ bool attachNothing = false;
};
// ============= Structure for caching shader uniforms ===============
@@ -106,7 +100,7 @@ public:
{
mVectors.push_back({ index, value });
}
-
+
void uniform4fv(S32 index, const F32* value)
{
mVectors.push_back({ index, LLVector4(value) });
@@ -117,8 +111,13 @@ public:
mVector3s.push_back({ index, value });
}
+ void uniform3fv(S32 index, const F32* value)
+ {
+ mVector3s.push_back({ index, LLVector3(value) });
+ }
+
void apply(LLGLSLShader* shader);
-
+
std::vector<IntSetting> mIntegers;
std::vector<FloatSetting> mFloats;
@@ -128,170 +127,206 @@ public:
class LLGLSLShader
{
public:
+ // NOTE: Keep gShaderConsts and LLGLSLShader::ShaderConsts_e in sync!
+ enum eShaderConsts
+ {
+ SHADER_CONST_CLOUD_MOON_DEPTH
+ , SHADER_CONST_STAR_DEPTH
+ , NUM_SHADER_CONSTS
+ };
// enum primarily used to control application sky settings uniforms
- typedef enum
- {
- SG_DEFAULT = 0, // not sky or water specific
- SG_SKY, //
- SG_WATER,
+ typedef enum
+ {
+ SG_DEFAULT = 0, // not sky or water specific
+ SG_SKY, //
+ SG_WATER,
SG_ANY,
SG_COUNT
- } eGroup;
-
- static std::set<LLGLSLShader*> sInstances;
- static bool sProfileEnabled;
-
- LLGLSLShader();
- ~LLGLSLShader();
-
- static GLhandleARB sCurBoundShader;
- static LLGLSLShader* sCurBoundShaderPtr;
- static S32 sIndexedTextureChannels;
-
- static void initProfile();
- static void finishProfile(bool emit_report = true);
-
- static void startProfile();
- static void stopProfile(U32 count, U32 mode);
-
- void unload();
- void clearStats();
- void dumpStats();
- void placeProfileQuery();
- void readProfileQuery(U32 count, U32 mode);
-
- BOOL createShader(std::vector<LLStaticHashedString> * attributes,
- std::vector<LLStaticHashedString> * uniforms,
- U32 varying_count = 0,
- const char** varyings = NULL);
+ } eGroup;
+
+ static std::set<LLGLSLShader*> sInstances;
+ static bool sProfileEnabled;
+
+ LLGLSLShader();
+ ~LLGLSLShader();
+
+ static GLuint sCurBoundShader;
+ static LLGLSLShader* sCurBoundShaderPtr;
+ static S32 sIndexedTextureChannels;
+
+ static void initProfile();
+ static void finishProfile(bool emit_report = true);
+
+ static void startProfile();
+ static void stopProfile();
+
+ void unload();
+ void clearStats();
+ void dumpStats();
+
+ // place query objects for profiling if profiling is enabled
+ // if for_runtime is true, will place timer query only whether or not profiling is enabled
+ void placeProfileQuery(bool for_runtime = false);
+
+ // Readback query objects if profiling is enabled
+ // If for_runtime is true, will readback timer query iff query is available
+ // Will return false if a query is pending (try again later)
+ // 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 attachFragmentObject(std::string object);
BOOL attachVertexObject(std::string object);
- void attachObject(GLhandleARB object);
- void attachObjects(GLhandleARB* 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> *);
- void uniform1i(U32 index, GLint i);
- void uniform1f(U32 index, GLfloat v);
- void uniform2f(U32 index, GLfloat x, GLfloat y);
- void uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z);
- void uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
- void uniform1iv(U32 index, U32 count, const GLint* i);
- void uniform1fv(U32 index, U32 count, const GLfloat* v);
- void uniform2fv(U32 index, U32 count, const GLfloat* v);
- void uniform3fv(U32 index, U32 count, const GLfloat* v);
- void uniform4fv(U32 index, U32 count, const GLfloat* v);
- void uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j);
- void uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
- void uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
- void uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
- void uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
- void uniform1i(const LLStaticHashedString& uniform, GLint i);
- void uniform1f(const LLStaticHashedString& uniform, GLfloat v);
- void uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y);
- void uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z);
- void uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
- void uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
- void uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
- void uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
- void uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat *v);
-
- void setMinimumAlpha(F32 minimum);
-
- void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
- void vertexAttrib4fv(U32 index, GLfloat* v);
-
- //GLint getUniformLocation(const std::string& uniform);
- GLint getUniformLocation(const LLStaticHashedString& uniform);
- GLint getUniformLocation(U32 index);
-
- GLint getAttribLocation(U32 attrib);
- GLint mapUniformTextureChannel(GLint location, GLenum type);
-
+ 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>*);
+ void uniform1i(U32 index, GLint i);
+ void uniform1f(U32 index, GLfloat v);
+ void fastUniform1f(U32 index, GLfloat v);
+ void uniform2f(U32 index, GLfloat x, GLfloat y);
+ void uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z);
+ void uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void uniform1iv(U32 index, U32 count, const GLint* i);
+ void uniform4iv(U32 index, U32 count, const GLint* i);
+ void uniform1fv(U32 index, U32 count, const GLfloat* v);
+ void uniform2fv(U32 index, U32 count, const GLfloat* v);
+ void uniform3fv(U32 index, U32 count, const GLfloat* v);
+ void uniform4fv(U32 index, U32 count, const GLfloat* v);
+ void uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j);
+ void uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v);
+ void uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v);
+ void uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v);
+ void uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v);
+ void uniform1i(const LLStaticHashedString& uniform, GLint i);
+ void uniform1iv(const LLStaticHashedString& uniform, U32 count, const GLint* v);
+ void uniform4iv(const LLStaticHashedString& uniform, U32 count, const GLint* v);
+ void uniform1f(const LLStaticHashedString& uniform, GLfloat v);
+ void uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y);
+ void uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z);
+ void uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
+ void uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
+ void uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
+ void uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
+ void uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat* v);
+
+ void setMinimumAlpha(F32 minimum);
+
+ void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void vertexAttrib4fv(U32 index, GLfloat* v);
+
+ //GLint getUniformLocation(const std::string& uniform);
+ GLint getUniformLocation(const LLStaticHashedString& uniform);
+ GLint getUniformLocation(U32 index);
+
+ GLint getAttribLocation(U32 attrib);
+ GLint mapUniformTextureChannel(GLint location, GLenum type, GLint size);
+
void clearPermutations();
- void addPermutation(std::string name, std::string value);
- void removePermutation(std::string name);
-
- //enable/disable texture channel for specified uniform
- //if given texture uniform is active in the shader,
- //the corresponding channel will be active upon return
- //returns channel texture is enabled in from [0-MAX)
- S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
+ void addPermutation(std::string name, std::string value);
+ void removePermutation(std::string name);
+
+ void addConstant(const LLGLSLShader::eShaderConsts shader_const);
+
+ //enable/disable texture channel for specified uniform
+ //if given texture uniform is active in the shader,
+ //the corresponding channel will be active upon return
+ //returns channel texture is enabled in from [0-MAX)
+ S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
-
- // bindTexture returns the texture unit we've bound the texture to.
- // You can reuse the return value to unbind a texture when required.
- S32 bindTexture(const std::string& uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
- S32 bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
- S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
- S32 unbindTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
-
+
+ // get the texture channel of the given uniform, or -1 if uniform is not used as a texture
+ S32 getTextureChannel(S32 uniform) const;
+
+ // bindTexture returns the texture unit we've bound the texture to.
+ // You can reuse the return value to unbind a texture when required.
+ S32 bindTexture(const std::string& uniform, LLTexture* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
+ S32 bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
+ S32 bindTexture(const std::string& uniform, LLRenderTarget* texture, bool depth = false, LLTexUnit::eTextureFilterOptions mode = LLTexUnit::TFO_BILINEAR);
+ S32 bindTexture(S32 uniform, LLRenderTarget* texture, bool depth = false, LLTexUnit::eTextureFilterOptions mode = LLTexUnit::TFO_BILINEAR, U32 index = 0);
+ S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+ S32 unbindTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+
BOOL link(BOOL suppress_errors = FALSE);
- void bind();
+ void bind();
//helper to conditionally bind mRiggedVariant instead of this
void bind(bool rigged);
- void unbind();
+
+ bool isComplete() const { return mProgramObject != 0; }
+
+ LLUUID hash();
- // Unbinds any previously bound shader by explicitly binding no shader.
- static void bindNoShader(void);
+ // Unbinds any previously bound shader by explicitly binding no shader.
+ static void unbind();
- U32 mMatHash[LLRender::NUM_MATRIX_MODES];
- U32 mLightHash;
+ U32 mMatHash[LLRender::NUM_MATRIX_MODES];
+ U32 mLightHash;
- GLhandleARB mProgramObject;
+ GLuint mProgramObject;
#if LL_RELEASE_WITH_DEBUG_INFO
- struct attr_name
- {
- GLint loc;
- const char *name;
- void operator = (GLint _loc) { loc = _loc; }
- operator GLint () { return loc; }
- };
- std::vector<attr_name> mAttribute; //lookup table of attribute enum to attribute channel
+ struct attr_name
+ {
+ GLint loc;
+ const char* name;
+ void operator = (GLint _loc) { loc = _loc; }
+ operator GLint () { return loc; }
+ };
+ std::vector<attr_name> mAttribute; //lookup table of attribute enum to attribute channel
#else
- std::vector<GLint> mAttribute; //lookup table of attribute enum to attribute channel
+ std::vector<GLint> mAttribute; //lookup table of attribute enum to attribute channel
#endif
- U32 mAttributeMask; //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask())
- std::vector<GLint> mUniform; //lookup table of uniform enum to uniform location
- LLStaticStringTable<GLint> mUniformMap; //lookup map of uniform name to uniform location
- typedef std::unordered_map<GLint, std::string> uniform_name_map_t;
+ U32 mAttributeMask; //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask())
+ std::vector<GLint> mUniform; //lookup table of uniform enum to uniform location
+ LLStaticStringTable<GLint> mUniformMap; //lookup map of uniform name to uniform location
typedef std::unordered_map<GLint, LLVector4> uniform_value_map_t;
- uniform_name_map_t mUniformNameMap; //lookup map of uniform location to uniform name
- uniform_value_map_t mValue; //lookup map of uniform location to last known value
- std::vector<GLint> mTexture;
- S32 mTotalUniformSize;
- S32 mActiveTextureChannels;
- S32 mShaderLevel;
- S32 mShaderGroup; // see LLGLSLShader::eGroup
- BOOL mUniformsDirty;
- LLShaderFeatures mFeatures;
- std::vector< std::pair< std::string, GLenum > > mShaderFiles;
- std::string mName;
- typedef std::unordered_map<std::string, std::string> defines_map_t;
- defines_map_t mDefines;
-
- //statistcis for profiling shader performance
- U32 mTimerQuery;
- U32 mSamplesQuery;
- U64 mTimeElapsed;
- static U64 sTotalTimeElapsed;
- U32 mTrianglesDrawn;
- static U32 sTotalTrianglesDrawn;
- U64 mSamplesDrawn;
- static U64 sTotalSamplesDrawn;
- U32 mDrawCalls;
- static U32 sTotalDrawCalls;
-
- bool mTextureStateFetched;
- std::vector<U32> mTextureMagFilter;
- std::vector<U32> mTextureMinFilter;
+ uniform_value_map_t mValue; //lookup map of uniform location to last known value
+ std::vector<GLint> mTexture;
+ S32 mTotalUniformSize;
+ S32 mActiveTextureChannels;
+ S32 mShaderLevel;
+ S32 mShaderGroup; // see LLGLSLShader::eGroup
+ BOOL mUniformsDirty;
+ LLShaderFeatures mFeatures;
+ std::vector< std::pair< std::string, GLenum > > mShaderFiles;
+ std::string mName;
+ typedef std::map<std::string, std::string> defines_map_t; //NOTE: this must be an ordered map to maintain hash consistency
+ defines_map_t mDefines;
+ static defines_map_t sGlobalDefines;
+ LLUUID mShaderHash;
+ bool mUsingBinaryProgram = false;
+
+ //statistics for profiling shader performance
+ bool mProfilePending = false;
+ U32 mTimerQuery;
+ U32 mSamplesQuery;
+ U32 mPrimitivesQuery;
+
+ U64 mTimeElapsed;
+ static U64 sTotalTimeElapsed;
+ U32 mTrianglesDrawn;
+ static U32 sTotalTrianglesDrawn;
+ U64 mSamplesDrawn;
+ static U64 sTotalSamplesDrawn;
+ U32 mBinds;
+ static U32 sTotalBinds;
// this pointer should be set to whichever shader represents this shader's rigged variant
LLGLSLShader* mRiggedVariant = nullptr;
+ // hacky flag used for optimization in LLDrawPoolAlpha
+ bool mCanBindFast = false;
+
+#ifdef LL_PROFILER_ENABLE_RENDER_DOC
+ void setLabel(const char* label);
+#endif
+
private:
- void unloadInternal();
+ void unloadInternal();
};
//UI shader (declared here so llui_libtest will link properly)
@@ -301,5 +336,10 @@ extern LLGLSLShader gSolidColorProgram;
//Alpha mask shader (declared here so llappearance can access properly)
extern LLGLSLShader gAlphaMaskProgram;
+#ifdef LL_PROFILER_ENABLE_RENDER_DOC
+#define LL_SET_SHADER_LABEL(shader) shader.setLabel(#shader)
+#else
+#define LL_SET_SHADER_LABEL(shader, label)
+#endif
#endif
diff --git a/indra/llrender/llglstates.h b/indra/llrender/llglstates.h
index a4924eba14..930c5e3ed7 100644
--- a/indra/llrender/llglstates.h
+++ b/indra/llrender/llglstates.h
@@ -56,100 +56,44 @@ private:
class LLGLSDefault
{
protected:
- LLGLEnable mColorMaterial;
- LLGLDisable mAlphaTest, mBlend, mCullFace, mDither, mFog,
- mLineSmooth, mLineStipple, mNormalize, mPolygonSmooth,
- mGLMultisample;
+ LLGLDisable mBlend, mCullFace;
public:
LLGLSDefault()
:
- // Enable
- mColorMaterial(GL_COLOR_MATERIAL),
// Disable
- mAlphaTest(GL_ALPHA_TEST),
mBlend(GL_BLEND),
- mCullFace(GL_CULL_FACE),
- mDither(GL_DITHER),
- mFog(GL_FOG),
- mLineSmooth(GL_LINE_SMOOTH),
- mLineStipple(GL_LINE_STIPPLE),
- mNormalize(GL_NORMALIZE),
- mPolygonSmooth(GL_POLYGON_SMOOTH),
- mGLMultisample(GL_MULTISAMPLE_ARB)
+ mCullFace(GL_CULL_FACE)
{ }
};
class LLGLSObjectSelect
{
protected:
- LLGLDisable mBlend, mFog, mAlphaTest;
+ LLGLDisable mBlend;
LLGLEnable mCullFace;
public:
LLGLSObjectSelect()
- : mBlend(GL_BLEND), mFog(GL_FOG),
- mAlphaTest(GL_ALPHA_TEST),
+ : mBlend(GL_BLEND),
mCullFace(GL_CULL_FACE)
{ }
};
-class LLGLSObjectSelectAlpha
-{
-protected:
- LLGLEnable mAlphaTest;
-public:
- LLGLSObjectSelectAlpha()
- : mAlphaTest(GL_ALPHA_TEST)
- {}
-};
-
//----------------------------------------------------------------------------
class LLGLSUIDefault
{
protected:
- LLGLEnable mBlend, mAlphaTest;
+ LLGLEnable mBlend;
LLGLDisable mCullFace;
LLGLDepthTest mDepthTest;
public:
LLGLSUIDefault()
- : mBlend(GL_BLEND), mAlphaTest(GL_ALPHA_TEST),
+ : mBlend(GL_BLEND),
mCullFace(GL_CULL_FACE),
mDepthTest(GL_FALSE, GL_TRUE, GL_LEQUAL)
{}
};
-class LLGLSNoAlphaTest // : public LLGLSUIDefault
-{
-protected:
- LLGLDisable mAlphaTest;
-public:
- LLGLSNoAlphaTest()
- : mAlphaTest(GL_ALPHA_TEST)
- {}
-};
-
-//----------------------------------------------------------------------------
-
-class LLGLSFog
-{
-protected:
- LLGLEnable mFog;
-public:
- LLGLSFog()
- : mFog(GL_FOG)
- {}
-};
-
-class LLGLSNoFog
-{
-protected:
- LLGLDisable mFog;
-public:
- LLGLSNoFog()
- : mFog(GL_FOG)
- {}
-};
-
//----------------------------------------------------------------------------
class LLGLSPipeline
@@ -167,21 +111,10 @@ public:
class LLGLSPipelineAlpha // : public LLGLSPipeline
{
protected:
- LLGLEnable mBlend, mAlphaTest;
+ LLGLEnable mBlend;
public:
LLGLSPipelineAlpha()
- : mBlend(GL_BLEND),
- mAlphaTest(GL_ALPHA_TEST)
- { }
-};
-
-class LLGLSPipelineEmbossBump
-{
-protected:
- LLGLDisable mFog;
-public:
- LLGLSPipelineEmbossBump()
- : mFog(GL_FOG)
+ : mBlend(GL_BLEND)
{ }
};
@@ -195,20 +128,9 @@ public:
{}
};
-class LLGLSPipelineAvatar
-{
-protected:
- LLGLEnable mNormalize;
-public:
- LLGLSPipelineAvatar()
- : mNormalize(GL_NORMALIZE)
- {}
-};
-
class LLGLSPipelineSkyBox
{
protected:
- LLGLDisable mAlphaTest;
LLGLDisable mCullFace;
LLGLSquashToFarClip mSquashClip;
public:
@@ -234,13 +156,11 @@ public:
class LLGLSTracker
{
protected:
- LLGLEnable mCullFace, mBlend, mAlphaTest;
+ LLGLEnable mCullFace, mBlend;
public:
LLGLSTracker() :
mCullFace(GL_CULL_FACE),
- mBlend(GL_BLEND),
- mAlphaTest(GL_ALPHA_TEST)
-
+ mBlend(GL_BLEND)
{ }
};
diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp
index e012eb9a62..7fdef4a3b7 100644
--- a/indra/llrender/llgltexture.cpp
+++ b/indra/llrender/llgltexture.cpp
@@ -27,25 +27,6 @@
#include "llgltexture.h"
-// static
-S32 LLGLTexture::getTotalNumOfCategories()
-{
- return MAX_GL_IMAGE_CATEGORY - (BOOST_HIGH - BOOST_SCULPTED) + 2 ;
-}
-
-// static
-//index starts from zero.
-S32 LLGLTexture::getIndexFromCategory(S32 category)
-{
- return (category < BOOST_HIGH) ? category : category - (BOOST_HIGH - BOOST_SCULPTED) + 1 ;
-}
-
-//static
-S32 LLGLTexture::getCategoryFromIndex(S32 index)
-{
- return (index < BOOST_HIGH) ? index : index + (BOOST_HIGH - BOOST_SCULPTED) - 1 ;
-}
-
LLGLTexture::LLGLTexture(BOOL usemipmaps)
{
init();
diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h
index 8cfe7b62de..5c693fc93c 100644
--- a/indra/llrender/llgltexture.h
+++ b/indra/llrender/llgltexture.h
@@ -49,10 +49,8 @@ public:
enum EBoostLevel
{
BOOST_NONE = 0,
- BOOST_ALM , //acts like NONE when ALM is on, max discard when ALM is off
- BOOST_AVATAR_BAKED ,
BOOST_AVATAR ,
- BOOST_CLOUDS ,
+ BOOST_AVATAR_BAKED ,
BOOST_SCULPTED ,
BOOST_HIGH = 10,
@@ -89,10 +87,6 @@ public:
NO_DELETE = 99 //stay in memory, can not be removed.
} LLGLTextureState;
- static S32 getTotalNumOfCategories() ;
- static S32 getIndexFromCategory(S32 category) ;
- static S32 getCategoryFromIndex(S32 index) ;
-
protected:
virtual ~LLGLTexture();
LOG_CLASS(LLGLTexture);
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 465f30a343..b77f98d65e 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -42,6 +42,8 @@
#include "llwindow.h"
#include "llframetimer.h"
+extern LL_COMMON_API bool on_main_thread();
+
#if !LL_IMAGEGL_THREAD_CHECK
#define checkActiveThread()
#endif
@@ -53,13 +55,75 @@ const F32 MIN_TEXTURE_LIFETIME = 10.f;
//assumes i is a power of 2 > 0
U32 wpo2(U32 i);
+
+// texture memory accounting (for OS X)
+static LLMutex sTexMemMutex;
+static std::unordered_map<U32, U32> sTextureAllocs;
+static U64 sTextureBytes = 0;
+
+// track a texture alloc on the currently bound texture.
+// asserts that no currently tracked alloc exists
+static void alloc_tex_image(U32 width, U32 height, U32 pixformat)
+{
+ U32 texUnit = gGL.getCurrentTexUnitIndex();
+ U32 texName = gGL.getTexUnit(texUnit)->getCurrTexture();
+ S32 size = LLImageGL::dataFormatBytes(pixformat, width, height);
+
+ llassert(size >= 0);
+
+ sTexMemMutex.lock();
+ llassert(sTextureAllocs.find(texName) == sTextureAllocs.end());
+
+ sTextureAllocs[texName] = size;
+ sTextureBytes += size;
+
+ sTexMemMutex.unlock();
+}
+
+// track texture free on given texName
+static void free_tex_image(U32 texName)
+{
+ sTexMemMutex.lock();
+ auto iter = sTextureAllocs.find(texName);
+ if (iter != sTextureAllocs.end())
+ {
+ llassert(iter->second <= sTextureBytes); // sTextureBytes MUST NOT go below zero
+
+ sTextureBytes -= iter->second;
+
+ sTextureAllocs.erase(iter);
+ }
+
+ sTexMemMutex.unlock();
+}
+
+// track texture free on given texNames
+static void free_tex_images(U32 count, const U32* texNames)
+{
+ for (int i = 0; i < count; ++i)
+ {
+ free_tex_image(texNames[i]);
+ }
+}
+
+// track texture free on currently bound texture
+static void free_cur_tex_image()
+{
+ U32 texUnit = gGL.getCurrentTexUnitIndex();
+ U32 texName = gGL.getTexUnit(texUnit)->getCurrTexture();
+ free_tex_image(texName);
+}
+
+// static
+U64 LLImageGL::getTextureBytesAllocated()
+{
+ return sTextureBytes;
+}
+
//statics
U32 LLImageGL::sUniqueCount = 0;
U32 LLImageGL::sBindCount = 0;
-S32Bytes LLImageGL::sGlobalTextureMemory(0);
-S32Bytes LLImageGL::sBoundTextureMemory(0);
-S32Bytes LLImageGL::sCurBoundTextureMemory(0);
S32 LLImageGL::sCount = 0;
BOOL LLImageGL::sGlobalUseAnisotropic = FALSE;
@@ -70,7 +134,8 @@ bool LLImageGL::sCompressTextures = false;
std::set<LLImageGL*> LLImageGL::sImageList;
-bool LLImageGLThread::sEnabled = false;
+bool LLImageGLThread::sEnabledTextures = false;
+bool LLImageGLThread::sEnabledMedia = false;
//****************************************************************************************************
//The below for texture auditing use only
@@ -180,14 +245,16 @@ BOOL is_little_endian()
}
//static
-void LLImageGL::initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha /* = false */, bool multi_threaded /* = false */)
+void LLImageGL::initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha /* = false */, bool thread_texture_loads /* = false */, bool thread_media_updates /* = false */)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
sSkipAnalyzeAlpha = skip_analyze_alpha;
- if (multi_threaded)
+ if (thread_texture_loads || thread_media_updates)
{
LLImageGLThread::createInstance(window);
+ LLImageGLThread::sEnabledTextures = thread_texture_loads;
+ LLImageGLThread::sEnabledMedia = thread_media_updates;
}
}
@@ -198,6 +265,7 @@ void LLImageGL::cleanupClass()
LLImageGLThread::deleteSingleton();
}
+
//static
S32 LLImageGL::dataFormatBits(S32 dataformat)
{
@@ -220,6 +288,7 @@ S32 LLImageGL::dataFormatBits(S32 dataformat)
case GL_RGBA: return 32;
case GL_SRGB_ALPHA: return 32;
case GL_BGRA: return 32; // Used for QuickTime media textures on the Mac
+ case GL_DEPTH_COMPONENT: return 24;
default:
LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL;
return 0;
@@ -282,15 +351,6 @@ void LLImageGL::updateStats(F32 current_time)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
sLastFrameTime = current_time;
- sBoundTextureMemory = sCurBoundTextureMemory;
- sCurBoundTextureMemory = S32Bytes(0);
-}
-
-//static
-S32 LLImageGL::updateBoundTexMem(const S32Bytes mem, const S32 ncomponents, S32 category)
-{
- LLImageGL::sCurBoundTextureMemory += mem ;
- return LLImageGL::sCurBoundTextureMemory.value();
}
//----------------------------------------------------------------------------
@@ -298,7 +358,7 @@ S32 LLImageGL::updateBoundTexMem(const S32Bytes mem, const S32 ncomponents, S32
//static
void LLImageGL::destroyGL(BOOL save_state)
{
- for (S32 stage = 0; stage < gGLManager.mNumTextureUnits; stage++)
+ for (S32 stage = 0; stage < gGLManager.mNumTextureImageUnits; stage++)
{
gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE);
}
@@ -466,7 +526,6 @@ void LLImageGL::init(BOOL usemipmaps)
mPickMaskHeight = 0;
mUseMipMaps = usemipmaps;
mHasExplicitFormat = FALSE;
- mAutoGenMips = FALSE;
mIsMask = FALSE;
mNeedsAlphaAndPickMask = TRUE ;
@@ -623,7 +682,7 @@ void LLImageGL::forceUpdateBindStats(void) const
mLastBindTime = sLastFrameTime;
}
-BOOL LLImageGL::updateBindStats(S32Bytes tex_mem) const
+BOOL LLImageGL::updateBindStats() const
{
if (mTexName != 0)
{
@@ -635,7 +694,6 @@ BOOL LLImageGL::updateBindStats(S32Bytes tex_mem) const
{
// we haven't accounted for this texture yet this frame
sUniqueCount++;
- updateBoundTexMem(tex_mem, mComponents, mCategory);
mLastBindTime = sLastFrameTime;
return TRUE ;
@@ -680,21 +738,8 @@ void LLImageGL::setImage(const LLImageRaw* imageraw)
BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips /* = FALSE */, S32 usename /* = 0 */)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- bool is_compressed = false;
- switch (mFormatPrimary)
- {
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
- is_compressed = true;
- break;
- default:
- break;
- }
+ const bool is_compressed = isCompressed();
if (mUseMipMaps)
{
@@ -741,7 +786,7 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips /* = FALSE */, S32
if (is_compressed)
{
S32 tex_size = dataFormatBytes(mFormatPrimary, w, h);
- glCompressedTexImage2DARB(mTarget, gl_level, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in);
+ glCompressedTexImage2D(mTarget, gl_level, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in);
stop_glerror();
}
else
@@ -812,6 +857,7 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips /* = FALSE */, S32
if (LLRender::sGLCoreProfile)
{
+ LL_PROFILE_GPU_ZONE("generate mip map");
glGenerateMipmap(mTarget);
}
stop_glerror();
@@ -943,7 +989,7 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips /* = FALSE */, S32
if (is_compressed)
{
S32 tex_size = dataFormatBytes(mFormatPrimary, w, h);
- glCompressedTexImage2DARB(mTarget, 0, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in);
+ glCompressedTexImage2D(mTarget, 0, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in);
stop_glerror();
}
else
@@ -1022,30 +1068,12 @@ BOOL LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image)
mFormatType = GL_UNSIGNED_BYTE;
break;
case 3:
-#if USE_SRGB_DECODE
- if (gGLManager.mHasTexturesRGBDecode)
- {
- mFormatInternal = GL_SRGB8;
- }
- else
-#endif
- {
- mFormatInternal = GL_RGB8;
- }
+ mFormatInternal = GL_RGB8;
mFormatPrimary = GL_RGB;
mFormatType = GL_UNSIGNED_BYTE;
break;
case 4:
-#if USE_SRGB_DECODE
- if (gGLManager.mHasTexturesRGBDecode)
- {
- mFormatInternal = GL_SRGB8_ALPHA8;
- }
- else
-#endif
- {
- mFormatInternal = GL_RGBA8;
- }
+ mFormatInternal = GL_RGBA8;
mFormatPrimary = GL_RGBA;
mFormatType = GL_UNSIGNED_BYTE;
break;
@@ -1085,6 +1113,60 @@ void LLImageGL::postAddToAtlas()
stop_glerror();
}
+U32 type_width_from_pixtype(U32 pixtype)
+{
+ U32 type_width = 0;
+ switch (pixtype)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_BYTE:
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ type_width = 1;
+ break;
+ case GL_UNSIGNED_SHORT:
+ case GL_SHORT:
+ type_width = 2;
+ break;
+ case GL_UNSIGNED_INT:
+ case GL_INT:
+ case GL_FLOAT:
+ type_width = 4;
+ break;
+ default:
+ LL_ERRS() << "Unknown type: " << pixtype << LL_ENDL;
+ }
+ return type_width;
+}
+
+bool should_stagger_image_set(bool compressed)
+{
+#if LL_DARWIN
+ return false;
+#else
+ // glTexSubImage2D doesn't work with compressed textures on select tested Nvidia GPUs on Windows 10 -Cosmic,2023-03-08
+ // Setting media textures off-thread seems faster when not using sub_image_lines (Nvidia/Windows 10) -Cosmic,2023-03-31
+ return !compressed && on_main_thread();
+#endif
+}
+
+// Equivalent to calling glSetSubImage2D(target, miplevel, x_offset, y_offset, width, height, pixformat, pixtype, src), assuming the total width of the image is data_width
+// However, instead there are multiple calls to glSetSubImage2D on smaller slices of the image
+void sub_image_lines(U32 target, S32 miplevel, S32 x_offset, S32 y_offset, S32 width, S32 height, U32 pixformat, U32 pixtype, const U8* src, S32 data_width)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+
+ U32 components = LLImageGL::dataFormatComponents(pixformat);
+ U32 type_width = type_width_from_pixtype(pixtype);
+
+ const U32 line_width = data_width * components * type_width;
+ const U32 y_offset_end = y_offset + height;
+ for (U32 y_pos = y_offset; y_pos < y_offset_end; ++y_pos)
+ {
+ glTexSubImage2D(target, miplevel, x_offset, y_pos, width, 1, pixformat, pixtype, src);
+ src += line_width;
+ }
+}
+
BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update /* = FALSE */, LLGLuint use_name)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
@@ -1159,13 +1241,25 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
stop_glerror();
}
- datap += (y_pos * data_width + x_pos) * getComponents();
+ const U8* sub_datap = datap + (y_pos * data_width + x_pos) * getComponents();
// Update the GL texture
BOOL res = gGL.getTexUnit(0)->bindManual(mBindTarget, tex_name);
if (!res) LL_ERRS() << "LLImageGL::setSubImage(): bindTexture failed" << LL_ENDL;
stop_glerror();
- glTexSubImage2D(mTarget, 0, x_pos, y_pos, width, height, mFormatPrimary, mFormatType, datap);
+ const bool use_sub_image = should_stagger_image_set(isCompressed());
+ if (!use_sub_image)
+ {
+ // *TODO: Why does this work here, in setSubImage, but not in
+ // setManualImage? Maybe because it only gets called with the
+ // dimensions of the full image? Or because the image is never
+ // compressed?
+ glTexSubImage2D(mTarget, 0, x_pos, y_pos, width, height, mFormatPrimary, mFormatType, sub_datap);
+ }
+ else
+ {
+ sub_image_lines(mTarget, 0, x_pos, y_pos, width, height, mFormatPrimary, mFormatType, sub_datap, data_width);
+ }
gGL.getTexUnit(0)->disable();
stop_glerror();
@@ -1238,6 +1332,7 @@ void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures)
{
if (gGLManager.mInited)
{
+ free_tex_images(numTextures, textures);
glDeleteTextures(numTextures, textures);
}
}
@@ -1330,7 +1425,8 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
}
}
- if (LLImageGL::sCompressTextures && allow_compression)
+ const bool compress = LLImageGL::sCompressTextures && allow_compression;
+ if (compress)
{
switch (intformat)
{
@@ -1375,7 +1471,32 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
stop_glerror();
{
LL_PROFILE_ZONE_NAMED("glTexImage2D");
- glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels);
+ LL_PROFILE_ZONE_NUM(width);
+ LL_PROFILE_ZONE_NUM(height);
+
+ free_cur_tex_image();
+ const bool use_sub_image = should_stagger_image_set(compress);
+ if (!use_sub_image)
+ {
+ LL_PROFILE_ZONE_NAMED("glTexImage2D alloc + copy");
+ glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels);
+ }
+ else
+ {
+ // break up calls to a manageable size for the GL command buffer
+ {
+ LL_PROFILE_ZONE_NAMED("glTexImage2D alloc");
+ glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, nullptr);
+ }
+
+ U8* src = (U8*)(use_scratch ? scratch : pixels);
+ if (src)
+ {
+ LL_PROFILE_ZONE_NAMED("glTexImage2D copy");
+ sub_image_lines(target, miplevel, 0, 0, width, height, pixformat, pixtype, src, width);
+ }
+ }
+ alloc_tex_image(width, height, pixformat);
}
stop_glerror();
@@ -1489,30 +1610,12 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
mFormatType = GL_UNSIGNED_BYTE;
break;
case 3:
- #if USE_SRGB_DECODE
- if (gGLManager.mHasTexturesRGBDecode)
- {
- mFormatInternal = GL_SRGB8;
- }
- else
- #endif
- {
- mFormatInternal = GL_RGB8;
- }
+ mFormatInternal = GL_RGB8;
mFormatPrimary = GL_RGB;
mFormatType = GL_UNSIGNED_BYTE;
break;
case 4:
- #if USE_SRGB_DECODE
- if (gGLManager.mHasTexturesRGBDecode)
- {
- mFormatInternal = GL_SRGB8_ALPHA8;
- }
- else
- #endif
- {
- mFormatInternal = GL_RGBA8;
- }
+ mFormatInternal = GL_RGBA8;
mFormatPrimary = GL_RGBA;
mFormatType = GL_UNSIGNED_BYTE;
break;
@@ -1541,6 +1644,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
// Call with void data, vmem is allocated but unitialized
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+ LL_PROFILE_GPU_ZONE("createGLTexture");
checkActiveThread();
bool main_thread = on_main_thread();
@@ -1600,7 +1704,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
if (mUseMipMaps)
{
- mAutoGenMips = gGLManager.mHasMipMapGeneration;
+ mAutoGenMips = true;
}
mCurrentDiscardLevel = discard_level;
@@ -1621,11 +1725,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
// things will break if we don't unbind after creation
gGL.getTexUnit(0)->unbind(mBindTarget);
- if (old_texname != 0)
- {
- sGlobalTextureMemory -= mTextureMemory;
- }
-
//if we're on the image loading thread, be sure to delete old_texname and update mTexName on the main thread
if (!defer_copy)
{
@@ -1646,7 +1745,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
mTextureMemory = (S32Bytes)getMipBytes(mCurrentDiscardLevel);
- sGlobalTextureMemory += mTextureMemory;
mTexelsInGLTexture = getWidth() * getHeight();
// mark this as bound at this point, so we don't throw it out immediately
@@ -1656,51 +1754,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
return TRUE;
}
-void LLImageGLThread::updateClass()
-{
- LL_PROFILE_ZONE_SCOPED;
-
- // update available vram one per second
- static LLFrameTimer sTimer;
-
- if (sTimer.getElapsedSeconds() < 1.f)
- {
- return;
- }
-
- sTimer.reset();
-
- auto func = []()
- {
- if (gGLManager.mHasATIMemInfo)
- {
- S32 meminfo[4];
- glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo);
- LLImageGLThread::sFreeVRAMMegabytes = meminfo[0];
-
- }
- else if (gGLManager.mHasNVXMemInfo)
- {
- S32 free_memory;
- glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory);
- LLImageGLThread::sFreeVRAMMegabytes = free_memory / 1024;
- }
- };
-
-
- // post update to background thread if available, otherwise execute immediately
- auto queue = LL::WorkQueue::getInstance("LLImageGL");
- if (sEnabled)
- {
- queue->post(func);
- }
- else
- {
- llassert(queue == nullptr);
- func();
- }
-}
-
void LLImageGL::syncToMainThread(LLGLuint new_tex_name)
{
LL_PROFILE_ZONE_SCOPED;
@@ -1708,7 +1761,16 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name)
{
LL_PROFILE_ZONE_NAMED("cglt - sync");
- if (gGLManager.mHasSync)
+ if (gGLManager.mIsNVIDIA)
+ {
+ // 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);
+ }
+ 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
@@ -1731,10 +1793,6 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name)
}
});
}
- else
- {
- glFinish();
- }
}
ref();
@@ -1746,8 +1804,11 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name)
syncTexName(new_tex_name);
unref();
});
+
+ LL_PROFILER_GPU_COLLECT;
}
+
void LLImageGL::syncTexName(LLGLuint texname)
{
if (texname != 0)
@@ -1837,7 +1898,7 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
return FALSE ;
}
- glGetCompressedTexImageARB(mTarget, gl_discard, (GLvoid*)(imageraw->getData()));
+ glGetCompressedTexImage(mTarget, gl_discard, (GLvoid*)(imageraw->getData()));
//stop_glerror();
}
else
@@ -1879,7 +1940,6 @@ void LLImageGL::destroyGLTexture()
{
if(mTextureMemory != S32Bytes(0))
{
- sGlobalTextureMemory -= mTextureMemory;
mTextureMemory = (S32Bytes)0;
}
@@ -2254,6 +2314,27 @@ void LLImageGL::freePickMask()
mPickMaskWidth = mPickMaskHeight = 0;
}
+bool LLImageGL::isCompressed()
+{
+ llassert(mFormatPrimary != 0);
+ // *NOTE: Not all compressed formats are included here.
+ bool is_compressed = false;
+ switch (mFormatPrimary)
+ {
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ is_compressed = true;
+ break;
+ default:
+ break;
+ }
+ return is_compressed;
+}
+
//----------------------------------------------------------------------------
void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
{
@@ -2431,21 +2512,16 @@ void LLImageGL::checkActiveThread()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, nummips);
*/
-std::atomic<S32> LLImageGLThread::sFreeVRAMMegabytes(4096); //if free vram is unknown, default to 4GB
-
LLImageGLThread::LLImageGLThread(LLWindow* window)
- // We want exactly one thread, but a very large capacity: we never want
- // anyone, especially inner-loop render code, to have to block on post()
- // because we're full.
- : ThreadPool("LLImageGL", 1, 1024*1024)
+ // We want exactly one thread.
+ : LL::ThreadPool("LLImageGL", 1)
, mWindow(window)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- sEnabled = true;
mFinished = false;
mContext = mWindow->createSharedContext();
- ThreadPool::start();
+ LL::ThreadPool::start();
}
void LLImageGLThread::run()
@@ -2455,13 +2531,8 @@ void LLImageGLThread::run()
// WorkQueue, likewise cleanup afterwards.
mWindow->makeContextCurrent(mContext);
gGL.init(false);
- ThreadPool::run();
+ LL::ThreadPool::run();
gGL.shutdown();
mWindow->destroySharedContext(mContext);
}
-S32 LLImageGLThread::getFreeVRAMMegabytes()
-{
- return sFreeVRAMMegabytes;
-}
-
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 4d5b60d6bc..243aeaea25 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -52,6 +52,13 @@ class LLImageGL : public LLRefCount
{
friend class LLTexUnit;
public:
+
+ // Get an estimate of how many bytes have been allocated in vram for textures.
+ // Does not include mipmaps.
+ // NOTE: multiplying this number by two gives a good estimate for total
+ // video memory usage based on testing in lagland against an NVIDIA GPU.
+ static U64 getTextureBytesAllocated();
+
// These 2 functions replace glGenTextures() and glDeleteTextures()
static void generateTextures(S32 numTextures, U32 *textures);
static void deleteTextures(S32 numTextures, const U32 *textures);
@@ -61,7 +68,7 @@ public:
static S32 dataFormatBytes(S32 dataformat, S32 width, S32 height);
static S32 dataFormatComponents(S32 dataformat);
- BOOL updateBindStats(S32Bytes tex_mem) const ;
+ BOOL updateBindStats() const ;
F32 getTimePassedSinceLastBound();
void forceUpdateBindStats(void) const;
@@ -73,9 +80,6 @@ public:
static void restoreGL();
static void dirtyTexOptions();
- // Sometimes called externally for textures not using LLImageGL (should go away...)
- static S32 updateBoundTexMem(const S32Bytes mem, const S32 ncomponents, S32 category) ;
-
static bool checkSize(S32 width, S32 height);
//for server side use only.
@@ -114,6 +118,9 @@ public:
BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0, bool defer_copy = false, LLGLuint* tex_name = nullptr);
void setImage(const LLImageRaw* imageraw);
BOOL setImage(const U8* data_in, BOOL data_hasmips = FALSE, S32 usename = 0);
+ // *TODO: This function may not work if the textures is compressed (i.e.
+ // RenderCompressTextures is 0). Partial image updates do not work on
+ // compressed textures.
BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE, LLGLuint use_name = 0);
BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE, LLGLuint use_name = 0);
BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height);
@@ -161,11 +168,11 @@ public:
BOOL getUseMipMaps() const { return mUseMipMaps; }
void setUseMipMaps(BOOL usemips) { mUseMipMaps = usemips; }
-
+ void setHasMipMaps(BOOL hasmips) { mHasMipMaps = hasmips; }
void updatePickMask(S32 width, S32 height, const U8* data_in);
BOOL getMask(const LLVector2 &tc);
- void checkTexSize(bool forced = false) const ;
+ void checkTexSize(bool forced = false) const ;
// Sets the addressing mode used to sample the texture
// (such as wrapping, mirrored wrapping, and clamp)
@@ -207,6 +214,7 @@ public:
private:
U32 createPickMask(S32 pWidth, S32 pHeight);
void freePickMask();
+ bool isCompressed();
LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL
LL::WorkQueue::weak_t mMainQueue;
@@ -215,7 +223,7 @@ private:
U16 mPickMaskHeight;
S8 mUseMipMaps;
BOOL mHasExplicitFormat; // If false (default), GL format is f(mComponents)
- S8 mAutoGenMips;
+ bool mAutoGenMips = false;
BOOL mIsMask;
BOOL mNeedsAlphaAndPickMask;
@@ -265,9 +273,6 @@ public:
static F32 sLastFrameTime;
// Global memory statistics
- static S32Bytes sGlobalTextureMemory; // Tracks main memory texmem
- static S32Bytes sBoundTextureMemory; // Tracks bound texmem for last completed frame
- static S32Bytes sCurBoundTextureMemory; // Tracks bound texmem for current frame
static U32 sBindCount; // Tracks number of texture binds for current frame
static U32 sUniqueCount; // Tracks number of unique texture binds for current frame
static BOOL sGlobalUseAnisotropic;
@@ -282,7 +287,7 @@ public:
#endif
public:
- static void initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha = false, bool multi_threaded = false);
+ static void initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha = false, bool thread_texture_loads = false, bool thread_media_updates = false);
static void cleanupClass() ;
private:
@@ -324,33 +329,26 @@ public:
class LLImageGLThread : public LLSimpleton<LLImageGLThread>, LL::ThreadPool
{
public:
- // follows gSavedSettings "RenderGLMultiThreaded"
- static bool sEnabled;
+ // follows gSavedSettings "RenderGLMultiThreadedTextures"
+ static bool sEnabledTextures;
+ // follows gSavedSettings "RenderGLMultiThreadedMedia"
+ static bool sEnabledMedia;
- // app should call this function periodically
- static void updateClass();
-
- // free video memory in megabytes
- static std::atomic<S32> sFreeVRAMMegabytes;
-
LLImageGLThread(LLWindow* window);
// post a function to be executed on the LLImageGL background thread
template <typename CALLABLE>
bool post(CALLABLE&& func)
{
- return getQueue().postIfOpen(std::forward<CALLABLE>(func));
+ return getQueue().post(std::forward<CALLABLE>(func));
}
void run() override;
- static S32 getFreeVRAMMegabytes();
-
private:
LLWindow* mWindow;
void* mContext = nullptr;
LLAtomicBool mFinished;
};
-
#endif // LL_LLIMAGEGL_H
diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp
index b6ea5aa7f1..0f8655132b 100644
--- a/indra/llrender/llpostprocess.cpp
+++ b/indra/llrender/llpostprocess.cpp
@@ -230,35 +230,7 @@ void LLPostProcess::applyShaders(void)
void LLPostProcess::applyColorFilterShader(void)
{
- /* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.
- gPostColorFilterProgram.bind();
-
- gGL.getTexUnit(0)->activate();
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE);
-
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, sceneRenderTexture);
-
- getShaderUniforms(colorFilterUniforms, gPostColorFilterProgram.mProgramObject);
- glUniform1iARB(colorFilterUniforms["RenderTexture"], 0);
- glUniform1fARB(colorFilterUniforms["brightness"], tweaks.getBrightness());
- glUniform1fARB(colorFilterUniforms["contrast"], tweaks.getContrast());
- float baseI = (tweaks.getContrastBaseR() + tweaks.getContrastBaseG() + tweaks.getContrastBaseB()) / 3.0f;
- baseI = tweaks.getContrastBaseIntensity() / ((baseI < 0.001f) ? 0.001f : baseI);
- float baseR = tweaks.getContrastBaseR() * baseI;
- float baseG = tweaks.getContrastBaseG() * baseI;
- float baseB = tweaks.getContrastBaseB() * baseI;
- glUniform3fARB(colorFilterUniforms["contrastBase"], baseR, baseG, baseB);
- glUniform1fARB(colorFilterUniforms["saturation"], tweaks.getSaturation());
- glUniform3fARB(colorFilterUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B);
- LLGLEnable blend(GL_BLEND);
- gGL.setSceneBlendType(LLRender::BT_REPLACE);
- LLGLDepthTest depth(GL_FALSE);
-
- /// Draw a screen space quad
- drawOrthoQuad(screenW, screenH, QUAD_NORMAL);
- gPostColorFilterProgram.unbind();
- */
}
void LLPostProcess::createColorFilterShader(void)
@@ -274,40 +246,7 @@ void LLPostProcess::createColorFilterShader(void)
void LLPostProcess::applyNightVisionShader(void)
{
- /* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.
- gPostNightVisionProgram.bind();
-
- gGL.getTexUnit(0)->activate();
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE);
-
- getShaderUniforms(nightVisionUniforms, gPostNightVisionProgram.mProgramObject);
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, sceneRenderTexture);
- glUniform1iARB(nightVisionUniforms["RenderTexture"], 0);
-
- gGL.getTexUnit(1)->activate();
- gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE);
-
- gGL.getTexUnit(1)->bindManual(LLTexUnit::TT_TEXTURE, noiseTexture);
- glUniform1iARB(nightVisionUniforms["NoiseTexture"], 1);
-
-
- glUniform1fARB(nightVisionUniforms["brightMult"], tweaks.getBrightMult());
- glUniform1fARB(nightVisionUniforms["noiseStrength"], tweaks.getNoiseStrength());
- noiseTextureScale = 0.01f + ((101.f - tweaks.getNoiseSize()) / 100.f);
- noiseTextureScale *= (screenH / NOISE_SIZE);
-
-
- glUniform3fARB(nightVisionUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B);
- LLGLEnable blend(GL_BLEND);
- gGL.setSceneBlendType(LLRender::BT_REPLACE);
- LLGLDepthTest depth(GL_FALSE);
-
- /// Draw a screen space quad
- drawOrthoQuad(screenW, screenH, QUAD_NOISE);
- gPostNightVisionProgram.unbind();
- gGL.getTexUnit(0)->activate();
- */
}
void LLPostProcess::createNightVisionShader(void)
@@ -345,12 +284,12 @@ void LLPostProcess::createBloomShader(void)
bloomBlurUniforms[sBlurWidth] = 0;
}
-void LLPostProcess::getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog)
+void LLPostProcess::getShaderUniforms(glslUniforms & uniforms, GLuint & prog)
{
/// Find uniform locations and insert into map
glslUniforms::iterator i;
for (i = uniforms.begin(); i != uniforms.end(); ++i){
- i->second = glGetUniformLocationARB(prog, i->first.String().c_str());
+ i->second = glGetUniformLocation(prog, i->first.String().c_str());
}
}
@@ -376,7 +315,7 @@ void LLPostProcess::doEffects(void)
checkError();
applyShaders();
- LLGLSLShader::bindNoShader();
+ LLGLSLShader::unbind();
checkError();
/// Change to a perspective view
@@ -390,84 +329,13 @@ void LLPostProcess::doEffects(void)
void LLPostProcess::copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height)
{
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture);
- glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 0, 0, width, height, 0);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture);
+ glCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, 0, 0, width, height, 0);
}
void LLPostProcess::drawOrthoQuad(unsigned int width, unsigned int height, QuadType type)
{
-#if 0
- float noiseX = 0.f;
- float noiseY = 0.f;
- float screenRatio = 1.0f;
-
- if (type == QUAD_NOISE){
- noiseX = ((float) rand() / (float) RAND_MAX);
- noiseY = ((float) rand() / (float) RAND_MAX);
- screenRatio = (float) width / (float) height;
- }
-
-
- glBegin(GL_QUADS);
- if (type != QUAD_BLOOM_EXTRACT){
- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, (GLfloat) height);
- } else {
- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, (GLfloat) height * 2.0f);
- }
- if (type == QUAD_NOISE){
- glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
- noiseX,
- noiseTextureScale + noiseY);
- } else if (type == QUAD_BLOOM_COMBINE){
- glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.f, (GLfloat) height * 0.5f);
- }
- glVertex2f(0.f, (GLfloat) screenH - height);
- if (type != QUAD_BLOOM_EXTRACT){
- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, 0.f);
- } else {
- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, 0.f);
- }
- if (type == QUAD_NOISE){
- glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
- noiseX,
- noiseY);
- } else if (type == QUAD_BLOOM_COMBINE){
- glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.f, 0.f);
- }
- glVertex2f(0.f, (GLfloat) height + (screenH - height));
-
-
- if (type != QUAD_BLOOM_EXTRACT){
- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width, 0.f);
- } else {
- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width * 2.0f, 0.f);
- }
- if (type == QUAD_NOISE){
- glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
- screenRatio * noiseTextureScale + noiseX,
- noiseY);
- } else if (type == QUAD_BLOOM_COMBINE){
- glMultiTexCoord2fARB(GL_TEXTURE1_ARB, (GLfloat) width * 0.5f, 0.f);
- }
- glVertex2f((GLfloat) width, (GLfloat) height + (screenH - height));
-
-
- if (type != QUAD_BLOOM_EXTRACT){
- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width, (GLfloat) height);
- } else {
- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width * 2.0f, (GLfloat) height * 2.0f);
- }
- if (type == QUAD_NOISE){
- glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
- screenRatio * noiseTextureScale + noiseX,
- noiseTextureScale + noiseY);
- } else if (type == QUAD_BLOOM_COMBINE){
- glMultiTexCoord2fARB(GL_TEXTURE1_ARB, (GLfloat) width * 0.5f, (GLfloat) height * 0.5f);
- }
- glVertex2f((GLfloat) width, (GLfloat) screenH - height);
- glEnd();
-#endif
}
void LLPostProcess::viewOrthogonal(unsigned int width, unsigned int height)
@@ -502,8 +370,8 @@ void LLPostProcess::createTexture(LLPointer<LLImageGL>& texture, unsigned int wi
texture = new LLImageGL(FALSE) ;
if(texture->createGLTexture())
{
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture->getTexName());
- glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0,
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture->getTexName());
+ glTexImage2D(GL_TEXTURE_RECTANGLE, 0, 4, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
@@ -557,7 +425,7 @@ bool LLPostProcess::checkError(void)
return retCode;
}
-void LLPostProcess::checkShaderError(GLhandleARB shader)
+void LLPostProcess::checkShaderError(GLuint shader)
{
GLint infologLength = 0;
GLint charsWritten = 0;
@@ -565,7 +433,7 @@ void LLPostProcess::checkShaderError(GLhandleARB shader)
checkError(); // Check for OpenGL errors
- glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength);
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength);
checkError(); // Check for OpenGL errors
@@ -577,7 +445,7 @@ void LLPostProcess::checkShaderError(GLhandleARB shader)
/// Could not allocate infolog buffer
return;
}
- glGetInfoLogARB(shader, infologLength, &charsWritten, infoLog);
+ glGetProgramInfoLog(shader, infologLength, &charsWritten, infoLog);
// shaderErrorLog << (char *) infoLog << std::endl;
mShaderErrorString = (char *) infoLog;
free(infoLog);
diff --git a/indra/llrender/llpostprocess.h b/indra/llrender/llpostprocess.h
index ce17b6693d..bdfc632831 100644
--- a/indra/llrender/llpostprocess.h
+++ b/indra/llrender/llpostprocess.h
@@ -249,12 +249,12 @@ private:
void applyColorFilterShader(void);
/// OpenGL Helper Functions
- void getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog);
+ void getShaderUniforms(glslUniforms & uniforms, GLuint & prog);
void createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height);
void copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height);
void createNoiseTexture(LLPointer<LLImageGL>& texture);
bool checkError(void);
- void checkShaderError(GLhandleARB shader);
+ void checkShaderError(GLuint shader);
void drawOrthoQuad(unsigned int width, unsigned int height, QuadType type);
void viewOrthogonal(unsigned int width, unsigned int height);
void changeOrthogonal(unsigned int width, unsigned int height);
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 72cca1f2a2..8430d13093 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -35,6 +35,7 @@
#include "llrendertarget.h"
#include "lltexture.h"
#include "llshadermgr.h"
+#include "hbxxh.h"
#if LL_WINDOWS
extern void APIENTRY gl_debug_callback(GLenum source,
@@ -54,8 +55,14 @@ F32 gGLModelView[16];
F32 gGLLastModelView[16];
F32 gGLLastProjection[16];
F32 gGLProjection[16];
+
+// transform from last frame's camera space to this frame's camera space (and inverse)
+F32 gGLDeltaModelView[16];
+F32 gGLInverseDeltaModelView[16];
+
S32 gGLViewport[4];
+
U32 LLRender::sUICalls = 0;
U32 LLRender::sUIVerts = 0;
U32 LLTexUnit::sWhiteTexture = 0;
@@ -63,14 +70,20 @@ bool LLRender::sGLCoreProfile = false;
bool LLRender::sNsightDebugSupport = false;
LLVector2 LLRender::sUIGLScaleFactor = LLVector2(1.f, 1.f);
-static const U32 LL_NUM_TEXTURE_LAYERS = 32;
-static const U32 LL_NUM_LIGHT_UNITS = 8;
+struct LLVBCache
+{
+ LLPointer<LLVertexBuffer> vb;
+ std::chrono::steady_clock::time_point touched;
+};
+
+static std::unordered_map<U64, LLVBCache> sVBCache;
static const GLenum sGLTextureType[] =
{
GL_TEXTURE_2D,
- GL_TEXTURE_RECTANGLE_ARB,
- GL_TEXTURE_CUBE_MAP_ARB,
+ GL_TEXTURE_RECTANGLE,
+ GL_TEXTURE_CUBE_MAP,
+ GL_TEXTURE_CUBE_MAP_ARRAY,
GL_TEXTURE_2D_MULTISAMPLE,
GL_TEXTURE_3D
};
@@ -122,7 +135,7 @@ void LLTexUnit::refreshState(void)
gGL.flush();
- glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
+ glActiveTexture(GL_TEXTURE0 + mIndex);
if (mCurrTexType != TT_NONE)
{
@@ -143,7 +156,7 @@ void LLTexUnit::activate(void)
if ((S32)gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty)
{
gGL.flush();
- glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
+ glActiveTexture(GL_TEXTURE0 + mIndex);
gGL.mCurrTextureUnitIndex = mIndex;
}
}
@@ -154,13 +167,10 @@ void LLTexUnit::enable(eTextureType type)
if ( (mCurrTexType != type || gGL.mDirty) && (type != TT_NONE) )
{
- stop_glerror();
activate();
- stop_glerror();
if (mCurrTexType != TT_NONE && !gGL.mDirty)
{
disable(); // Force a disable of a previous texture type if it's enabled.
- stop_glerror();
}
mCurrTexType = type;
@@ -174,11 +184,7 @@ void LLTexUnit::disable(void)
if (mCurrTexType != TT_NONE)
{
- activate();
unbind(mCurrTexType);
- gGL.flush();
- setTextureColorSpace(TCS_LINEAR);
-
mCurrTexType = TT_NONE;
}
}
@@ -186,8 +192,8 @@ void LLTexUnit::disable(void)
void LLTexUnit::bindFast(LLTexture* texture)
{
LLImageGL* gl_tex = texture->getGLTexture();
-
- glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
+ texture->setActive();
+ glActiveTexture(GL_TEXTURE0 + mIndex);
gGL.mCurrTextureUnitIndex = mIndex;
mCurrTexture = gl_tex->getTexName();
if (!mCurrTexture)
@@ -223,7 +229,7 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
enable(gl_tex->getTarget());
mCurrTexture = gl_tex->getTexName();
glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture);
- if(gl_tex->updateBindStats(gl_tex->mTextureMemory))
+ if(gl_tex->updateBindStats())
{
texture->setActive() ;
texture->updateBindStatsForTester() ;
@@ -302,7 +308,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind, S32
mCurrTexture = texname;
glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture);
stop_glerror();
- texture->updateBindStats(texture->mTextureMemory);
+ texture->updateBindStats();
mHasMipMaps = texture->mHasMipMaps;
if (texture->mTexOptionsDirty)
{
@@ -334,14 +340,14 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap)
if (mCurrTexture != cubeMap->mImages[0]->getTexName())
{
- if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
+ if (LLCubeMap::sUseCubeMaps)
{
activate();
enable(LLTexUnit::TT_CUBE_MAP);
mCurrTexture = cubeMap->mImages[0]->getTexName();
- glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mCurrTexture);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, mCurrTexture);
mHasMipMaps = cubeMap->mImages[0]->mHasMipMaps;
- cubeMap->mImages[0]->updateBindStats(cubeMap->mImages[0]->mTextureMemory);
+ cubeMap->mImages[0]->updateBindStats();
if (cubeMap->mImages[0]->mTexOptionsDirty)
{
cubeMap->mImages[0]->mTexOptionsDirty = false;
@@ -369,10 +375,7 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth)
if (bindDepth)
{
- if (renderTarget->hasStencil())
- {
- LL_ERRS() << "Cannot bind a render buffer for sampling. Allocate render target without a stencil buffer if sampling of depth buffer is required." << LL_ENDL;
- }
+ llassert(renderTarget->getDepth()); // target MUST have a depth buffer attachment
bindManual(renderTarget->getUsage(), renderTarget->getDepth());
}
@@ -469,7 +472,7 @@ void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode)
glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_T, sGLAddressMode[mode]);
if (mCurrTexType == TT_CUBE_MAP)
{
- glTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, sGLAddressMode[mode]);
+ glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, sGLAddressMode[mode]);
}
}
@@ -515,22 +518,15 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio
}
}
- if (gGLManager.mHasAnisotropic)
+ if (gGLManager.mGLVersion >= 4.59f)
{
if (LLImageGL::sGlobalUseAnisotropic && option == TFO_ANISOTROPIC)
{
- if (gGL.mMaxAnisotropy < 1.f)
- {
- glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gGL.mMaxAnisotropy);
-
- LL_INFOS() << "gGL.mMaxAnisotropy: " << gGL.mMaxAnisotropy << LL_ENDL ;
- gGL.mMaxAnisotropy = llmax(1.f, gGL.mMaxAnisotropy) ;
- }
- glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, gGL.mMaxAnisotropy);
+ glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY, gGLManager.mMaxAnisotropy);
}
else
{
- glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f);
+ glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY, 1.f);
}
}
}
@@ -544,7 +540,7 @@ GLint LLTexUnit::getTextureSource(eTextureBlendSrc src)
case TBS_PREV_ALPHA:
case TBS_ONE_MINUS_PREV_COLOR:
case TBS_ONE_MINUS_PREV_ALPHA:
- return GL_PREVIOUS_ARB;
+ return GL_PREVIOUS;
// All four cases should return the same value.
case TBS_TEX_COLOR:
@@ -558,18 +554,18 @@ GLint LLTexUnit::getTextureSource(eTextureBlendSrc src)
case TBS_VERT_ALPHA:
case TBS_ONE_MINUS_VERT_COLOR:
case TBS_ONE_MINUS_VERT_ALPHA:
- return GL_PRIMARY_COLOR_ARB;
+ return GL_PRIMARY_COLOR;
// All four cases should return the same value.
case TBS_CONST_COLOR:
case TBS_CONST_ALPHA:
case TBS_ONE_MINUS_CONST_COLOR:
case TBS_ONE_MINUS_CONST_ALPHA:
- return GL_CONSTANT_ARB;
+ return GL_CONSTANT;
default:
LL_WARNS() << "Unknown eTextureBlendSrc: " << src << ". Using Vertex Color instead." << LL_ENDL;
- return GL_PRIMARY_COLOR_ARB;
+ return GL_PRIMARY_COLOR;
}
}
@@ -638,10 +634,10 @@ void LLTexUnit::debugTextureUnit(void)
if (mIndex < 0) return;
GLint activeTexture;
- glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &activeTexture);
- if ((GL_TEXTURE0_ARB + mIndex) != activeTexture)
+ glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture);
+ if ((GL_TEXTURE0 + mIndex) != activeTexture)
{
- U32 set_unit = (activeTexture - GL_TEXTURE0_ARB);
+ U32 set_unit = (activeTexture - GL_TEXTURE0);
LL_WARNS() << "Incorrect Texture Unit! Expected: " << set_unit << " Actual: " << mIndex << LL_ENDL;
}
}
@@ -649,29 +645,6 @@ void LLTexUnit::debugTextureUnit(void)
void LLTexUnit::setTextureColorSpace(eTextureColorSpace space)
{
mTexColorSpace = space;
-
-#if USE_SRGB_DECODE
- if (gGLManager.mHasTexturesRGBDecode)
- {
- if (space == TCS_SRGB)
- {
- glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
- }
- else
- {
- glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
- }
-
- if (gDebugGL)
- {
- assert_glerror();
- }
- }
- else
- {
- glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
- }
-#endif
}
LLLightState::LLLightState(S32 index)
@@ -734,6 +707,24 @@ void LLLightState::setSunPrimary(bool v)
}
}
+void LLLightState::setSize(F32 v)
+{
+ if (mSize != v)
+ {
+ ++gGL.mLightHash;
+ mSize = v;
+ }
+}
+
+void LLLightState::setFalloff(F32 v)
+{
+ if (mFalloff != v)
+ {
+ ++gGL.mLightHash;
+ mFalloff = v;
+ }
+}
+
void LLLightState::setAmbient(const LLColor4& ambient)
{
if (mAmbient != ambient)
@@ -827,19 +818,16 @@ LLRender::LLRender()
mCount(0),
mQuadCycle(0),
mMode(LLRender::TRIANGLES),
- mCurrTextureUnitIndex(0),
- mMaxAnisotropy(0.f)
+ mCurrTextureUnitIndex(0)
{
- mTexUnits.reserve(LL_NUM_TEXTURE_LAYERS);
for (U32 i = 0; i < LL_NUM_TEXTURE_LAYERS; i++)
{
- mTexUnits.push_back(new LLTexUnit(i));
+ mTexUnits[i].mIndex = i;
}
- mDummyTexUnit = new LLTexUnit(-1);
for (U32 i = 0; i < LL_NUM_LIGHT_UNITS; ++i)
{
- mLightState.push_back(new LLLightState(i));
+ mLightState[i].mIndex = i;
}
for (U32 i = 0; i < 4; i++)
@@ -874,9 +862,9 @@ void LLRender::init(bool needs_vertex_buffer)
#if LL_WINDOWS
if (gGLManager.mHasDebugOutput && gDebugGL)
{ //setup debug output callback
- //glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, GL_TRUE);
- glDebugMessageCallbackARB((GLDEBUGPROCARB) gl_debug_callback, NULL);
- glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
+ //glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, GL_TRUE);
+ glDebugMessageCallback((GLDEBUGPROC) gl_debug_callback, NULL);
+ glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
}
#endif
@@ -888,14 +876,14 @@ void LLRender::init(bool needs_vertex_buffer)
glCullFace(GL_BACK);
- if (sGLCoreProfile && !LLVertexBuffer::sUseVAO)
- { //bind a dummy vertex array object so we're core profile compliant
-#ifdef GL_ARB_vertex_array_object
- U32 ret;
- glGenVertexArrays(1, &ret);
- glBindVertexArray(ret);
-#endif
- }
+ // necessary for reflection maps
+ glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+
+ { //bind a dummy vertex array object so we're core profile compliant
+ U32 ret;
+ glGenVertexArrays(1, &ret);
+ glBindVertexArray(ret);
+ }
if (needs_vertex_buffer)
{
@@ -907,8 +895,8 @@ void LLRender::initVertexBuffer()
{
llassert_always(mBuffer.isNull());
stop_glerror();
- mBuffer = new LLVertexBuffer(immediate_mask, 0);
- mBuffer->allocateBuffer(4096, 0, TRUE);
+ mBuffer = new LLVertexBuffer(immediate_mask);
+ mBuffer->allocateBuffer(4096, 0);
mBuffer->getVertexStrider(mVerticesp);
mBuffer->getTexCoord0Strider(mTexcoordsp);
mBuffer->getColorStrider(mColorsp);
@@ -922,19 +910,6 @@ void LLRender::resetVertexBuffer()
void LLRender::shutdown()
{
- for (U32 i = 0; i < mTexUnits.size(); i++)
- {
- delete mTexUnits[i];
- }
- mTexUnits.clear();
- delete mDummyTexUnit;
- mDummyTexUnit = NULL;
-
- for (U32 i = 0; i < mLightState.size(); ++i)
- {
- delete mLightState[i];
- }
- mLightState.clear();
resetVertexBuffer();
}
@@ -946,10 +921,10 @@ void LLRender::refreshState(void)
for (U32 i = 0; i < mTexUnits.size(); i++)
{
- mTexUnits[i]->refreshState();
+ mTexUnits[i].refreshState();
}
- mTexUnits[active_unit]->activate();
+ mTexUnits[active_unit].activate();
setColorMask(mCurrColorMask[0], mCurrColorMask[1], mCurrColorMask[2], mCurrColorMask[3]);
@@ -977,10 +952,11 @@ void LLRender::syncLightState()
LLVector3 diffuse[LL_NUM_LIGHT_UNITS];
LLVector3 diffuse_b[LL_NUM_LIGHT_UNITS];
bool sun_primary[LL_NUM_LIGHT_UNITS];
+ LLVector2 size[LL_NUM_LIGHT_UNITS];
for (U32 i = 0; i < LL_NUM_LIGHT_UNITS; i++)
{
- LLLightState *light = mLightState[i];
+ LLLightState *light = &mLightState[i];
position[i] = light->mPosition;
direction[i] = light->mSpotDirection;
@@ -988,17 +964,19 @@ void LLRender::syncLightState()
diffuse[i].set(light->mDiffuse.mV);
diffuse_b[i].set(light->mDiffuseB.mV);
sun_primary[i] = light->mSunIsPrimary;
+ size[i].set(light->mSize, light->mFalloff);
}
shader->uniform4fv(LLShaderMgr::LIGHT_POSITION, LL_NUM_LIGHT_UNITS, position[0].mV);
shader->uniform3fv(LLShaderMgr::LIGHT_DIRECTION, LL_NUM_LIGHT_UNITS, direction[0].mV);
shader->uniform4fv(LLShaderMgr::LIGHT_ATTENUATION, LL_NUM_LIGHT_UNITS, attenuation[0].mV);
+ shader->uniform2fv(LLShaderMgr::LIGHT_DEFERRED_ATTENUATION, LL_NUM_LIGHT_UNITS, size[0].mV);
shader->uniform3fv(LLShaderMgr::LIGHT_DIFFUSE, LL_NUM_LIGHT_UNITS, diffuse[0].mV);
- shader->uniform4fv(LLShaderMgr::LIGHT_AMBIENT, 1, mAmbientLightColor.mV);
+ shader->uniform3fv(LLShaderMgr::LIGHT_AMBIENT, 1, mAmbientLightColor.mV);
shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_primary[0] ? 1 : 0);
- shader->uniform4fv(LLShaderMgr::AMBIENT, 1, mAmbientLightColor.mV);
- shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, 1, diffuse[0].mV);
- shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, diffuse_b[0].mV);
+ //shader->uniform3fv(LLShaderMgr::AMBIENT, 1, mAmbientLightColor.mV);
+ shader->uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, 1, diffuse[0].mV);
+ shader->uniform3fv(LLShaderMgr::MOONLIGHT_COLOR, 1, diffuse_b[0].mV);
}
}
@@ -1095,13 +1073,20 @@ void LLRender::syncMatrices()
{ //update projection matrix, normal, and MVP
glh::matrix4f& mat = mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]];
- // it would be nice to have this automatically track the state of the proj matrix
- // but certain render paths (deferred lighting) require it to be mismatched *sigh*
- //if (shader->getUniformLocation(LLShaderMgr::INVERSE_PROJECTION_MATRIX))
- //{
- // glh::matrix4f inv_proj = mat.inverse();
- // shader->uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, inv_proj.m);
- //}
+ // GZ: This was previously disabled seemingly due to a bug involving the deferred renderer's regular pushing and popping of mats.
+ // We're reenabling this and cleaning up the code around that - that would've been the appropriate course initially.
+ // Anything beyond the standard proj and inv proj mats are special cases. Please setup special uniforms accordingly in the future.
+ if (shader->getUniformLocation(LLShaderMgr::INVERSE_PROJECTION_MATRIX))
+ {
+ glh::matrix4f inv_proj = mat.inverse();
+ shader->uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, inv_proj.m);
+ }
+
+ // Used by some full screen effects - such as full screen lights, glow, etc.
+ if (shader->getUniformLocation(LLShaderMgr::IDENTITY_MATRIX))
+ {
+ shader->uniformMatrix4fv(LLShaderMgr::IDENTITY_MATRIX, 1, GL_FALSE, glh::matrix4f::identity().m);
+ }
shader->uniformMatrix4fv(name[MM_PROJECTION], 1, GL_FALSE, mat.m);
shader->mMatHash[MM_PROJECTION] = mMatHash[MM_PROJECTION];
@@ -1479,12 +1464,7 @@ void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor,
llassert(color_dfactor < BF_UNDEF);
llassert(alpha_sfactor < BF_UNDEF);
llassert(alpha_dfactor < BF_UNDEF);
- if (!gGLManager.mHasBlendFuncSeparate)
- {
- LL_WARNS_ONCE("render") << "no glBlendFuncSeparateEXT(), using color-only blend func" << LL_ENDL;
- blendFunc(color_sfactor, color_dfactor);
- return;
- }
+
if (mCurrBlendColorSFactor != color_sfactor || mCurrBlendColorDFactor != color_dfactor ||
mCurrBlendAlphaSFactor != alpha_sfactor || mCurrBlendAlphaDFactor != alpha_dfactor)
{
@@ -1493,8 +1473,9 @@ void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor,
mCurrBlendColorDFactor = color_dfactor;
mCurrBlendAlphaDFactor = alpha_dfactor;
flush();
- glBlendFuncSeparateEXT(sGLBlendFactor[color_sfactor], sGLBlendFactor[color_dfactor],
- sGLBlendFactor[alpha_sfactor], sGLBlendFactor[alpha_dfactor]);
+
+ glBlendFuncSeparate(sGLBlendFactor[color_sfactor], sGLBlendFactor[color_dfactor],
+ sGLBlendFactor[alpha_sfactor], sGLBlendFactor[alpha_dfactor]);
}
}
@@ -1502,12 +1483,12 @@ LLTexUnit* LLRender::getTexUnit(U32 index)
{
if (index < mTexUnits.size())
{
- return mTexUnits[index];
+ return &mTexUnits[index];
}
else
{
LL_DEBUGS() << "Non-existing texture unit layer requested: " << index << LL_ENDL;
- return mDummyTexUnit;
+ return &mDummyTexUnit;
}
}
@@ -1515,7 +1496,7 @@ LLLightState* LLRender::getLight(U32 index)
{
if (index < mLightState.size())
{
- return mLightState[index];
+ return &mLightState[index];
}
return NULL;
@@ -1599,6 +1580,7 @@ void LLRender::flush()
if (mCount > 0)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+ llassert(LLGLSLShader::sCurBoundShaderPtr != nullptr);
if (!mUIOffset.empty())
{
sUICalls++;
@@ -1639,24 +1621,108 @@ void LLRender::flush()
if (mBuffer)
{
- if (mBuffer->useVBOs() && !mBuffer->isLocked())
- { //hack to only flush the part of the buffer that was updated (relies on stream draw using buffersubdata)
- mBuffer->getVertexStrider(mVerticesp, 0, count);
- mBuffer->getTexCoord0Strider(mTexcoordsp, 0, count);
- mBuffer->getColorStrider(mColorsp, 0, count);
+
+ HBXXH64 hash;
+ U32 attribute_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask;
+
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache hash");
+
+ hash.update((U8*)mVerticesp.get(), count * sizeof(LLVector4a));
+ if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0)
+ {
+ hash.update((U8*)mTexcoordsp.get(), count * sizeof(LLVector2));
+ }
+
+ if (attribute_mask & LLVertexBuffer::MAP_COLOR)
+ {
+ hash.update((U8*)mColorsp.get(), count * sizeof(LLColor4U));
+ }
+
+ hash.finalize();
+ }
+
+
+ U64 vhash = hash.digest();
+
+ // check the VB cache before making a new vertex buffer
+ // This is a giant hack to deal with (mostly) our terrible UI rendering code
+ // that was built on top of OpenGL immediate mode. Huge performance wins
+ // can be had by not uploading geometry to VRAM unless absolutely necessary.
+ // Most of our usage of the "immediate mode" style draw calls is actually
+ // sending the same geometry over and over again.
+ // To leverage this, we maintain a running hash of the vertex stream being
+ // built up before a flush, and then check that hash against a VB
+ // cache just before creating a vertex buffer in VRAM
+ std::unordered_map<U64, LLVBCache>::iterator cache = sVBCache.find(vhash);
+
+ LLPointer<LLVertexBuffer> vb;
+
+ if (cache != sVBCache.end())
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache hit");
+ // cache hit, just use the cached buffer
+ vb = cache->second.vb;
+ cache->second.touched = std::chrono::steady_clock::now();
+ }
+ else
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache miss");
+ vb = new LLVertexBuffer(attribute_mask);
+ vb->allocateBuffer(count, 0);
+
+ vb->setBuffer();
+
+ vb->setPositionData((LLVector4a*) mVerticesp.get());
+
+ if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0)
+ {
+ vb->setTexCoordData(mTexcoordsp.get());
+ }
+
+ if (attribute_mask & LLVertexBuffer::MAP_COLOR)
+ {
+ vb->setColorData(mColorsp.get());
+ }
+
+ vb->unbind();
+
+ sVBCache[vhash] = { vb , std::chrono::steady_clock::now() };
+
+ static U32 miss_count = 0;
+ miss_count++;
+ if (miss_count > 1024)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache clean");
+ miss_count = 0;
+ auto now = std::chrono::steady_clock::now();
+
+ using namespace std::chrono_literals;
+ // every 1024 misses, clean the cache of any VBs that haven't been touched in the last second
+ for (std::unordered_map<U64, LLVBCache>::iterator iter = sVBCache.begin(); iter != sVBCache.end(); )
+ {
+ if (now - iter->second.touched > 1s)
+ {
+ iter = sVBCache.erase(iter);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+ }
}
- mBuffer->flush();
- mBuffer->setBuffer(immediate_mask);
+ vb->setBuffer();
if (mMode == LLRender::QUADS && sGLCoreProfile)
{
- mBuffer->drawArrays(LLRender::TRIANGLES, 0, count);
+ vb->drawArrays(LLRender::TRIANGLES, 0, count);
mQuadCycle = 1;
}
else
{
- mBuffer->drawArrays(mMode, 0, count);
+ vb->drawArrays(mMode, 0, count);
}
}
else
@@ -1948,8 +2014,7 @@ void LLRender::texCoord2fv(const GLfloat* tc)
void LLRender::color4ub(const GLubyte& r, const GLubyte& g, const GLubyte& b, const GLubyte& a)
{
- if (!LLGLSLShader::sCurBoundShaderPtr ||
- LLGLSLShader::sCurBoundShaderPtr->mAttributeMask & LLVertexBuffer::MAP_COLOR)
+ if (!LLGLSLShader::sCurBoundShaderPtr || LLGLSLShader::sCurBoundShaderPtr->mAttributeMask & LLVertexBuffer::MAP_COLOR)
{
mColorsp[mCount] = LLColor4U(r,g,b,a);
}
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 9c36c230fb..98141d71f5 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -52,7 +52,10 @@ class LLTexture ;
#define LL_MATRIX_STACK_DEPTH 32
-class LLTexUnit
+constexpr U32 LL_NUM_TEXTURE_LAYERS = 32;
+constexpr U32 LL_NUM_LIGHT_UNITS = 8;
+
+class LLTexUnit
{
friend class LLRender;
public:
@@ -63,6 +66,7 @@ public:
TT_TEXTURE = 0, // Standard 2D Texture
TT_RECT_TEXTURE, // Non power of 2 texture
TT_CUBE_MAP, // 6-sided cube map texture
+ TT_CUBE_MAP_ARRAY, // Array of cube maps
TT_MULTISAMPLE_TEXTURE, // see GL_ARB_texture_multisample
TT_TEXTURE_3D, // standard 3D Texture
TT_NONE, // No texture type is currently enabled
@@ -83,6 +87,13 @@ public:
TFO_ANISOTROPIC // Equal to: min=anisotropic, max=anisotropic, mip=linear.
} eTextureFilterOptions;
+ typedef enum
+ {
+ TMG_NONE = 0, // Mipmaps are not automatically generated for this texture.
+ TMG_AUTO, // Mipmaps are automatically generated for this texture.
+ TMG_MANUAL // Mipmaps are manually generated for this texture.
+ } eTextureMipGeneration;
+
typedef enum
{
TB_REPLACE = 0,
@@ -134,7 +145,7 @@ public:
TCS_SRGB
} eTextureColorSpace;
- LLTexUnit(S32 index);
+ LLTexUnit(S32 index = -1);
// Refreshes renderer state of the texture unit to the cached values
// Needed when the render context has changed and invalidated the current state
@@ -211,7 +222,9 @@ public:
eTextureColorSpace getCurrColorSpace() { return mTexColorSpace; }
protected:
- const S32 mIndex;
+ friend class LLRender;
+
+ S32 mIndex;
U32 mCurrTexture;
eTextureType mCurrTexType;
eTextureColorSpace mTexColorSpace;
@@ -229,7 +242,7 @@ protected:
class LLLightState
{
public:
- LLLightState(S32 index);
+ LLLightState(S32 index = -1);
void enable();
void disable();
@@ -245,6 +258,8 @@ public:
void setSpotCutoff(const F32& cutoff);
void setSpotDirection(const LLVector3& direction);
void setSunPrimary(bool v);
+ void setSize(F32 size);
+ void setFalloff(F32 falloff);
protected:
friend class LLRender;
@@ -265,6 +280,8 @@ protected:
F32 mSpotExponent;
F32 mSpotCutoff;
+ F32 mSize = 0.f;
+ F32 mFalloff = 0.f;
};
class LLRender
@@ -272,7 +289,7 @@ class LLRender
friend class LLTexUnit;
public:
- enum eTexIndex
+ enum eTexIndex : U8
{
DIFFUSE_MAP = 0,
ALTERNATE_DIFFUSE_MAP = 1,
@@ -281,14 +298,15 @@ public:
NUM_TEXTURE_CHANNELS = 3,
};
- enum eVolumeTexIndex
+ enum eVolumeTexIndex : U8
{
LIGHT_TEX = 0,
SCULPT_TEX,
NUM_VOLUME_TEXTURE_CHANNELS,
};
- typedef enum {
+ enum eGeomModes : U8
+ {
TRIANGLES = 0,
TRIANGLE_STRIP,
TRIANGLE_FAN,
@@ -298,9 +316,9 @@ public:
QUADS,
LINE_LOOP,
NUM_MODES
- } eGeomModes;
+ };
- typedef enum
+ enum eCompareFunc : U8
{
CF_NEVER = 0,
CF_ALWAYS,
@@ -311,9 +329,9 @@ public:
CF_GREATER_EQUAL,
CF_GREATER,
CF_DEFAULT
- } eCompareFunc;
+ };
- typedef enum
+ enum eBlendType : U8
{
BT_ALPHA = 0,
BT_ADD,
@@ -322,25 +340,26 @@ public:
BT_MULT_ALPHA,
BT_MULT_X2,
BT_REPLACE
- } eBlendType;
+ };
- typedef enum
+ // WARNING: this MUST match the LL_PART_BF enum in LLPartData, so set values explicitly in case someone
+ // decides to add more or reorder them
+ enum eBlendFactor : U8
{
BF_ONE = 0,
- BF_ZERO,
- BF_DEST_COLOR,
- BF_SOURCE_COLOR,
- BF_ONE_MINUS_DEST_COLOR,
- BF_ONE_MINUS_SOURCE_COLOR,
- BF_DEST_ALPHA,
- BF_SOURCE_ALPHA,
- BF_ONE_MINUS_DEST_ALPHA,
- BF_ONE_MINUS_SOURCE_ALPHA,
-
+ BF_ZERO = 1,
+ BF_DEST_COLOR = 2,
+ BF_SOURCE_COLOR = 3,
+ BF_ONE_MINUS_DEST_COLOR = 4,
+ BF_ONE_MINUS_SOURCE_COLOR = 5,
+ BF_DEST_ALPHA = 6,
+ BF_SOURCE_ALPHA = 7,
+ BF_ONE_MINUS_DEST_ALPHA = 8,
+ BF_ONE_MINUS_SOURCE_ALPHA = 9,
BF_UNDEF
- } eBlendFactor;
+ };
- typedef enum
+ enum eMatrixMode : U8
{
MM_MODELVIEW = 0,
MM_PROJECTION,
@@ -350,7 +369,7 @@ public:
MM_TEXTURE3,
NUM_MATRIX_MODES,
MM_TEXTURE
- } eMatrixMode;
+ };
LLRender();
~LLRender();
@@ -481,17 +500,15 @@ private:
LLStrider<LLVector3> mVerticesp;
LLStrider<LLVector2> mTexcoordsp;
LLStrider<LLColor4U> mColorsp;
- std::vector<LLTexUnit*> mTexUnits;
- LLTexUnit* mDummyTexUnit;
- std::vector<LLLightState*> mLightState;
+ std::array<LLTexUnit, LL_NUM_TEXTURE_LAYERS> mTexUnits;
+ LLTexUnit mDummyTexUnit;
+ std::array<LLLightState, LL_NUM_LIGHT_UNITS> mLightState;
eBlendFactor mCurrBlendColorSFactor;
eBlendFactor mCurrBlendColorDFactor;
eBlendFactor mCurrBlendAlphaSFactor;
eBlendFactor mCurrBlendAlphaDFactor;
- F32 mMaxAnisotropy;
-
std::vector<LLVector3> mUIOffset;
std::vector<LLVector3> mUIScale;
@@ -502,6 +519,8 @@ extern F32 gGLLastModelView[16];
extern F32 gGLLastProjection[16];
extern F32 gGLProjection[16];
extern S32 gGLViewport[4];
+extern F32 gGLDeltaModelView[16];
+extern F32 gGLInverseDeltaModelView[16];
extern thread_local LLRender gGL;
@@ -526,12 +545,7 @@ glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar);
glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up);
-#if LL_RELEASE_FOR_DOWNLOAD
- #define LL_SHADER_LOADING_WARNS(...) LL_WARNS_ONCE("ShaderLoading")
- #define LL_SHADER_UNIFORM_ERRS(...) LL_WARNS_ONCE("Shader")
-#else
- #define LL_SHADER_LOADING_WARNS(...) LL_WARNS()
- #define LL_SHADER_UNIFORM_ERRS(...) LL_ERRS("Shader")
-#endif
+#define LL_SHADER_LOADING_WARNS(...) LL_WARNS()
+#define LL_SHADER_UNIFORM_ERRS(...) LL_ERRS("Shader")
#endif
diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp
index 5cb1dc6b25..52869406d2 100644
--- a/indra/llrender/llrender2dutils.cpp
+++ b/indra/llrender/llrender2dutils.cpp
@@ -117,7 +117,6 @@ void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixe
void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled )
{
- stop_glerror();
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
// Counterclockwise quad will face the viewer
@@ -142,7 +141,6 @@ void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled )
gGL.vertex2i(left, top);
gGL.end();
}
- stop_glerror();
}
void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled )
@@ -714,11 +712,8 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
}
}
-void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase )
+void gl_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color)
{
- // Stippled line
- LLGLEnable stipple(GL_LINE_STIPPLE);
-
gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], color.mV[VALPHA]);
gGL.flush();
@@ -1516,7 +1511,15 @@ void LLRender2D::loadIdentity()
void LLRender2D::setLineWidth(F32 width)
{
gGL.flush();
- glLineWidth(width * lerp(LLRender::sUIGLScaleFactor.mV[VX], LLRender::sUIGLScaleFactor.mV[VY], 0.5f));
+ // If outside the allowed range, glLineWidth fails with "invalid value".
+ // On Darwin, the range is [1, 1].
+ static GLfloat range[2]{0.0};
+ if (range[1] == 0)
+ {
+ glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, range);
+ }
+ width *= lerp(LLRender::sUIGLScaleFactor.mV[VX], LLRender::sUIGLScaleFactor.mV[VY], 0.5f);
+ glLineWidth(llclamp(width, range[0], range[1]));
}
LLPointer<LLUIImage> LLRender2D::getUIImageByID(const LLUUID& image_id, S32 priority)
diff --git a/indra/llrender/llrender2dutils.h b/indra/llrender/llrender2dutils.h
index 206e68f084..135738c3ba 100644
--- a/indra/llrender/llrender2dutils.h
+++ b/indra/llrender/llrender2dutils.h
@@ -79,7 +79,7 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), bool scale_inner = true);
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f), bool scale_inner = true);
-void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f );
+void gl_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color);
void gl_rect_2d_simple_tex( S32 width, S32 height );
diff --git a/indra/llrender/llrendernavprim.cpp b/indra/llrender/llrendernavprim.cpp
index ca72964832..d610a44bc6 100644
--- a/indra/llrender/llrendernavprim.cpp
+++ b/indra/llrender/llrendernavprim.cpp
@@ -53,7 +53,7 @@ void LLRenderNavPrim::renderLLTri( const LLVector3& a, const LLVector3& b, const
//=============================================================================
void LLRenderNavPrim::renderNavMeshVB( U32 mode, LLVertexBuffer* pVBO, int vertCnt )
{
- pVBO->setBuffer( LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_NORMAL );
+ pVBO->setBuffer();
pVBO->drawArrays( mode, 0, vertCnt );
}
//=============================================================================
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index fffc15efc3..88c48e5166 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -35,19 +35,19 @@ U32 LLRenderTarget::sBytesAllocated = 0;
void check_framebuffer_status()
{
- if (gDebugGL)
- {
- GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
- switch (status)
- {
- case GL_FRAMEBUFFER_COMPLETE:
- break;
- default:
- LL_WARNS() << "check_framebuffer_status failed -- " << std::hex << status << LL_ENDL;
- ll_fail("check_framebuffer_status failed");
- break;
- }
- }
+ if (gDebugGL)
+ {
+ GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+ switch (status)
+ {
+ case GL_FRAMEBUFFER_COMPLETE:
+ break;
+ default:
+ LL_WARNS() << "check_framebuffer_status failed -- " << std::hex << status << LL_ENDL;
+ ll_fail("check_framebuffer_status failed");
+ break;
+ }
+ }
}
bool LLRenderTarget::sUseFBO = false;
@@ -60,114 +60,93 @@ U32 LLRenderTarget::sCurResX = 0;
U32 LLRenderTarget::sCurResY = 0;
LLRenderTarget::LLRenderTarget() :
- mResX(0),
- mResY(0),
- mFBO(0),
- mPreviousFBO(0),
- mPreviousResX(0),
- mPreviousResY(0),
- mDepth(0),
- mStencil(0),
- mUseDepth(false),
- mRenderDepth(false),
- mUsage(LLTexUnit::TT_TEXTURE)
+ mResX(0),
+ mResY(0),
+ mFBO(0),
+ mDepth(0),
+ mUseDepth(false),
+ mUsage(LLTexUnit::TT_TEXTURE)
{
}
LLRenderTarget::~LLRenderTarget()
{
- release();
+ release();
}
void LLRenderTarget::resize(U32 resx, U32 resy)
{
- //for accounting, get the number of pixels added/subtracted
- S32 pix_diff = (resx*resy)-(mResX*mResY);
-
- mResX = resx;
- mResY = resy;
-
- llassert(mInternalFormat.size() == mTex.size());
-
- for (U32 i = 0; i < mTex.size(); ++i)
- { //resize color attachments
- gGL.getTexUnit(0)->bindManual(mUsage, mTex[i]);
- LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, mInternalFormat[i], mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false);
- sBytesAllocated += pix_diff*4;
- }
-
- if (mDepth)
- { //resize depth attachment
- if (mStencil)
- {
- //use render buffers where stencil buffers are in play
- glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mResX, mResY);
- glBindRenderbuffer(GL_RENDERBUFFER, 0);
- }
- else
- {
- 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);
- }
-
- sBytesAllocated += pix_diff*4;
- }
+ //for accounting, get the number of pixels added/subtracted
+ S32 pix_diff = (resx*resy)-(mResX*mResY);
+
+ mResX = resx;
+ mResY = resy;
+
+ llassert(mInternalFormat.size() == mTex.size());
+
+ for (U32 i = 0; i < mTex.size(); ++i)
+ { //resize color attachments
+ gGL.getTexUnit(0)->bindManual(mUsage, mTex[i]);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, mInternalFormat[i], mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false);
+ sBytesAllocated += pix_diff*4;
+ }
+
+ if (mDepth)
+ {
+ 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);
+
+ sBytesAllocated += pix_diff*4;
+ }
}
-
+
-bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)
+bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, LLTexUnit::eTextureType usage, LLTexUnit::eTextureMipGeneration generateMipMaps)
{
- resx = llmin(resx, (U32) gGLManager.mGLMaxTextureSize);
- resy = llmin(resy, (U32) gGLManager.mGLMaxTextureSize);
-
- stop_glerror();
- release();
- stop_glerror();
-
- mResX = resx;
- mResY = resy;
-
- mStencil = stencil;
- mUsage = usage;
- mUseDepth = depth;
-
- if (sUseFBO || use_fbo)
- {
- if (depth)
- {
- if (!allocateDepth())
- {
- LL_WARNS() << "Failed to allocate depth buffer for render target." << LL_ENDL;
- return false;
- }
- }
-
- glGenFramebuffers(1, (GLuint *) &mFBO);
-
- if (mDepth)
- {
- glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
- if (mStencil)
- {
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth);
- stop_glerror();
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth);
- stop_glerror();
- }
- else
- {
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
- stop_glerror();
- }
- glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
- }
-
- stop_glerror();
- }
-
- return addColorAttachment(color_fmt);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ llassert(usage == LLTexUnit::TT_TEXTURE);
+ llassert(!isBoundInStack());
+
+ resx = llmin(resx, (U32) gGLManager.mGLMaxTextureSize);
+ resy = llmin(resy, (U32) gGLManager.mGLMaxTextureSize);
+
+ release();
+
+ mResX = resx;
+ mResY = resy;
+
+ mUsage = usage;
+ mUseDepth = depth;
+
+ mGenerateMipMaps = generateMipMaps;
+
+ if (mGenerateMipMaps != LLTexUnit::TMG_NONE) {
+ // Calculate the number of mip levels based upon resolution that we should have.
+ mMipLevels = 1 + floor(log10((float)llmax(mResX, mResY))/log10(2.0));
+ }
+
+ if (depth)
+ {
+ if (!allocateDepth())
+ {
+ LL_WARNS() << "Failed to allocate depth buffer for render target." << LL_ENDL;
+ return false;
+ }
+ }
+
+ glGenFramebuffers(1, (GLuint *) &mFBO);
+
+ if (mDepth)
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
+ }
+
+ return addColorAttachment(color_fmt);
}
void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name)
@@ -177,6 +156,7 @@ void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name)
llassert(sUseFBO); // FBO support must be enabled
llassert(mDepth == 0); // depth buffers not supported with this mode
llassert(mTex.empty()); // mTex must be empty with this mode (binding target should be done via LLImageGL)
+ llassert(!isBoundInStack());
if (mFBO == 0)
{
@@ -207,6 +187,7 @@ void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name)
void LLRenderTarget::releaseColorAttachment()
{
LL_PROFILE_ZONE_SCOPED;
+ llassert(!isBoundInStack());
llassert(mTex.size() == 1); //cannot use releaseColorAttachment with LLRenderTarget managed color targets
llassert(mFBO != 0); // mFBO must be valid
@@ -219,340 +200,297 @@ void LLRenderTarget::releaseColorAttachment()
bool LLRenderTarget::addColorAttachment(U32 color_fmt)
{
- if (color_fmt == 0)
- {
- return true;
- }
-
- U32 offset = mTex.size();
-
- if( offset >= 4 )
- {
- LL_WARNS() << "Too many color attachments" << LL_ENDL;
- llassert( offset < 4 );
- return false;
- }
- if( offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers) )
- {
- LL_WARNS() << "FBO not used or no drawbuffers available; mFBO=" << (U32)mFBO << " gGLManager.mHasDrawBuffers=" << (U32)gGLManager.mHasDrawBuffers << LL_ENDL;
- llassert( mFBO != 0 );
- llassert( gGLManager.mHasDrawBuffers );
- return false;
- }
-
- U32 tex;
- LLImageGL::generateTextures(1, &tex);
- gGL.getTexUnit(0)->bindManual(mUsage, tex);
-
- stop_glerror();
-
-
- {
- clear_glerror();
- LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false);
- if (glGetError() != GL_NO_ERROR)
- {
- LL_WARNS() << "Could not allocate color buffer for render target." << LL_ENDL;
- return false;
- }
- }
-
- 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();
- }
- else
- { //don't filter data attachments
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
- stop_glerror();
- }
-
- if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
- {
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
- stop_glerror();
- }
- else
- {
- // ATI doesn't support mirrored repeat for rectangular textures.
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
- stop_glerror();
- }
-
- if (mFBO)
- {
- stop_glerror();
- glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset,
- LLTexUnit::getInternalType(mUsage), tex, 0);
- stop_glerror();
-
- check_framebuffer_status();
-
- glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
- }
-
- mTex.push_back(tex);
- mInternalFormat.push_back(color_fmt);
-
-#if !LL_DARWIN
- if (gDebugGL)
- { //bind and unbind to validate target
- bindTarget();
- flush();
- }
-#endif
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ llassert(!isBoundInStack());
+
+ if (color_fmt == 0)
+ {
+ return true;
+ }
+
+ U32 offset = mTex.size();
+
+ if( offset >= 4 )
+ {
+ LL_WARNS() << "Too many color attachments" << LL_ENDL;
+ llassert( offset < 4 );
+ return false;
+ }
+ if( offset > 0 && (mFBO == 0) )
+ {
+ llassert( mFBO != 0 );
+ return false;
+ }
+
+ U32 tex;
+ LLImageGL::generateTextures(1, &tex);
+ gGL.getTexUnit(0)->bindManual(mUsage, tex);
+
+ stop_glerror();
+
+
+ {
+ clear_glerror();
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false);
+ if (glGetError() != GL_NO_ERROR)
+ {
+ LL_WARNS() << "Could not allocate color buffer for render target." << LL_ENDL;
+ return false;
+ }
+ }
+ sBytesAllocated += mResX*mResY*4;
+
+ stop_glerror();
+
- return true;
+ if (offset == 0)
+ { //use bilinear filtering on single texture render targets that aren't multisampled
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ stop_glerror();
+ }
+ else
+ { //don't filter data attachments
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ stop_glerror();
+ }
+
+ if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
+ {
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
+ stop_glerror();
+ }
+ else
+ {
+ // ATI doesn't support mirrored repeat for rectangular textures.
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ stop_glerror();
+ }
+
+ if (mFBO)
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset,
+ LLTexUnit::getInternalType(mUsage), tex, 0);
+
+ check_framebuffer_status();
+
+ glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
+ }
+
+ mTex.push_back(tex);
+ mInternalFormat.push_back(color_fmt);
+
+ if (gDebugGL)
+ { //bind and unbind to validate target
+ bindTarget();
+ flush();
+ }
+
+
+ return true;
}
bool LLRenderTarget::allocateDepth()
{
- if (mStencil)
- {
- //use render buffers where stencil buffers are in play
- glGenRenderbuffers(1, (GLuint *) &mDepth);
- glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
- stop_glerror();
- clear_glerror();
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mResX, mResY);
- glBindRenderbuffer(GL_RENDERBUFFER, 0);
- }
- else
- {
- LLImageGL::generateTextures(1, &mDepth);
- 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);
- }
-
- sBytesAllocated += mResX*mResY*4;
-
- if (glGetError() != GL_NO_ERROR)
- {
- LL_WARNS() << "Unable to allocate depth buffer for render target." << LL_ENDL;
- return false;
- }
-
- return true;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ LLImageGL::generateTextures(1, &mDepth);
+ 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);
+
+ sBytesAllocated += mResX*mResY*4;
+
+ if (glGetError() != GL_NO_ERROR)
+ {
+ LL_WARNS() << "Unable to allocate depth buffer for render target." << LL_ENDL;
+ return false;
+ }
+
+ return true;
}
void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)
{
- if (!mFBO || !target.mFBO)
- {
- LL_ERRS() << "Cannot share depth buffer between non FBO render targets." << LL_ENDL;
- }
-
- if (target.mDepth)
- {
- LL_ERRS() << "Attempting to override existing depth buffer. Detach existing buffer first." << LL_ENDL;
- }
-
- if (target.mUseDepth)
- {
- LL_ERRS() << "Attempting to override existing shared depth buffer. Detach existing buffer first." << LL_ENDL;
- }
-
- if (mDepth)
- {
- stop_glerror();
- glBindFramebuffer(GL_FRAMEBUFFER, target.mFBO);
- stop_glerror();
-
- if (mStencil)
- {
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth);
- stop_glerror();
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth);
- stop_glerror();
- target.mStencil = true;
- }
- else
- {
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
- stop_glerror();
- }
-
- check_framebuffer_status();
-
- glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
-
- target.mUseDepth = true;
- }
+ llassert(!isBoundInStack());
+
+ if (!mFBO || !target.mFBO)
+ {
+ LL_ERRS() << "Cannot share depth buffer between non FBO render targets." << LL_ENDL;
+ }
+
+ if (target.mDepth)
+ {
+ LL_ERRS() << "Attempting to override existing depth buffer. Detach existing buffer first." << LL_ENDL;
+ }
+
+ if (target.mUseDepth)
+ {
+ LL_ERRS() << "Attempting to override existing shared depth buffer. Detach existing buffer first." << LL_ENDL;
+ }
+
+ if (mDepth)
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, target.mFBO);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
+
+ check_framebuffer_status();
+
+ glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
+
+ target.mUseDepth = true;
+ }
}
void LLRenderTarget::release()
{
- if (mDepth)
- {
- if (mStencil)
- {
- glDeleteRenderbuffers(1, (GLuint*) &mDepth);
- stop_glerror();
- }
- else
- {
- LLImageGL::deleteTextures(1, &mDepth);
- stop_glerror();
- }
- mDepth = 0;
-
- sBytesAllocated -= mResX*mResY*4;
- }
- else if (mFBO)
- {
- glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
-
- if (mUseDepth)
- { //detach shared depth buffer
- if (mStencil)
- { //attached as a renderbuffer
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
- mStencil = false;
- }
- else
- { //attached as a texture
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0);
- }
- mUseDepth = false;
- }
- }
-
- // Detach any extra color buffers (e.g. SRGB spec buffers)
- //
- if (mFBO && (mTex.size() > 1))
- {
- glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
- S32 z;
- for (z = mTex.size() - 1; z >= 1; z--)
- {
- sBytesAllocated -= mResX*mResY*4;
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+z, LLTexUnit::getInternalType(mUsage), 0, 0);
- stop_glerror();
- LLImageGL::deleteTextures(1, &mTex[z]);
- }
- }
-
- if (mFBO)
- {
- glDeleteFramebuffers(1, (GLuint *) &mFBO);
- stop_glerror();
- mFBO = 0;
- }
-
- if (mTex.size() > 0)
- {
- sBytesAllocated -= mResX*mResY*4;
- LLImageGL::deleteTextures(1, &mTex[0]);
- }
-
- mTex.clear();
- mInternalFormat.clear();
-
- mResX = mResY = 0;
-
- sBoundTarget = NULL;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ llassert(!isBoundInStack());
+
+ if (mDepth)
+ {
+ LLImageGL::deleteTextures(1, &mDepth);
+
+ mDepth = 0;
+
+ sBytesAllocated -= mResX*mResY*4;
+ }
+ else if (mFBO)
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+
+ if (mUseDepth)
+ { //detach shared depth buffer
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0);
+ mUseDepth = false;
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
+ }
+
+ // Detach any extra color buffers (e.g. SRGB spec buffers)
+ //
+ if (mFBO && (mTex.size() > 1))
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+ S32 z;
+ for (z = mTex.size() - 1; z >= 1; z--)
+ {
+ sBytesAllocated -= mResX*mResY*4;
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+z, LLTexUnit::getInternalType(mUsage), 0, 0);
+ LLImageGL::deleteTextures(1, &mTex[z]);
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
+ }
+
+ if (mFBO)
+ {
+ if (mFBO == sCurFBO)
+ {
+ sCurFBO = 0;
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
+
+ glDeleteFramebuffers(1, (GLuint *) &mFBO);
+ mFBO = 0;
+ }
+
+ if (mTex.size() > 0)
+ {
+ sBytesAllocated -= mResX*mResY*4;
+ LLImageGL::deleteTextures(1, &mTex[0]);
+ }
+
+ mTex.clear();
+ mInternalFormat.clear();
+
+ mResX = mResY = 0;
}
void LLRenderTarget::bindTarget()
{
- if (mFBO)
- {
- stop_glerror();
-
- mPreviousFBO = sCurFBO;
- glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
- sCurFBO = mFBO;
-
- stop_glerror();
- if (gGLManager.mHasDrawBuffers)
- { //setup multiple render targets
- GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
- GL_COLOR_ATTACHMENT1,
- GL_COLOR_ATTACHMENT2,
- GL_COLOR_ATTACHMENT3};
- LL_PROFILER_GPU_ZONEC( "gl.DrawBuffersARB", 0x4000FF )
- glDrawBuffersARB(mTex.size(), drawbuffers);
- }
-
- if (mTex.empty())
- { //no color buffer to draw to
- LL_PROFILER_GPU_ZONEC( "gl.DrawBuffer", 0x0000FF )
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
- }
-
- check_framebuffer_status();
-
- stop_glerror();
- }
-
- mPreviousResX = sCurResX;
- mPreviousResY = sCurResY;
- glViewport(0, 0, mResX, mResY);
- sCurResX = mResX;
- sCurResY = mResY;
-
- sBoundTarget = this;
+ LL_PROFILE_GPU_ZONE("bindTarget");
+ llassert(mFBO);
+ llassert(!isBoundInStack());
+
+ glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+ sCurFBO = mFBO;
+
+ //setup multiple render targets
+ GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
+ GL_COLOR_ATTACHMENT1,
+ GL_COLOR_ATTACHMENT2,
+ GL_COLOR_ATTACHMENT3};
+ glDrawBuffers(mTex.size(), drawbuffers);
+
+ if (mTex.empty())
+ { //no color buffer to draw to
+ glDrawBuffer(GL_NONE);
+ glReadBuffer(GL_NONE);
+ }
+
+ check_framebuffer_status();
+
+ glViewport(0, 0, mResX, mResY);
+ sCurResX = mResX;
+ sCurResY = mResY;
+
+ mPreviousRT = sBoundTarget;
+ sBoundTarget = this;
}
void LLRenderTarget::clear(U32 mask_in)
{
- U32 mask = GL_COLOR_BUFFER_BIT;
- if (mUseDepth)
- {
- mask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
- }
- if (mFBO)
- {
- check_framebuffer_status();
- stop_glerror();
- glClear(mask & mask_in);
- stop_glerror();
- }
- else
- {
- LLGLEnable scissor(GL_SCISSOR_TEST);
- glScissor(0, 0, mResX, mResY);
- stop_glerror();
- glClear(mask & mask_in);
- }
+ LL_PROFILE_GPU_ZONE("clear");
+ llassert(mFBO);
+ U32 mask = GL_COLOR_BUFFER_BIT;
+ if (mUseDepth)
+ {
+ mask |= GL_DEPTH_BUFFER_BIT;
+
+ }
+ if (mFBO)
+ {
+ check_framebuffer_status();
+ stop_glerror();
+ glClear(mask & mask_in);
+ stop_glerror();
+ }
+ else
+ {
+ LLGLEnable scissor(GL_SCISSOR_TEST);
+ glScissor(0, 0, mResX, mResY);
+ stop_glerror();
+ glClear(mask & mask_in);
+ }
}
U32 LLRenderTarget::getTexture(U32 attachment) const
{
- if (attachment > mTex.size()-1)
- {
- LL_ERRS() << "Invalid attachment index." << LL_ENDL;
- }
- if (mTex.empty())
- {
- return 0;
- }
- return mTex[attachment];
+ if (attachment > mTex.size()-1)
+ {
+ LL_ERRS() << "Invalid attachment index." << LL_ENDL;
+ }
+ if (mTex.empty())
+ {
+ return 0;
+ }
+ return mTex[attachment];
}
U32 LLRenderTarget::getNumTextures() const
{
- return mTex.size();
+ return mTex.size();
}
void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options)
{
- gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index));
+ gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index), filter_options == LLTexUnit::TFO_TRILINEAR || filter_options == LLTexUnit::TFO_ANISOTROPIC);
bool isSRGB = false;
llassert(mInternalFormat.size() > index);
@@ -573,137 +511,60 @@ void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilt
gGL.getTexUnit(channel)->setTextureColorSpace(isSRGB ? LLTexUnit::TCS_SRGB : LLTexUnit::TCS_LINEAR);
}
-void LLRenderTarget::flush(bool fetch_depth)
-{
- gGL.flush();
- if (!mFBO)
- {
- gGL.getTexUnit(0)->bind(this);
- glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, 0, 0, 0, 0, mResX, mResY);
-
- if (fetch_depth)
- {
- if (!mDepth)
- {
- allocateDepth();
- }
-
- gGL.getTexUnit(0)->bind(this);
- glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8, 0, 0, mResX, mResY, 0);
- }
-
- gGL.getTexUnit(0)->disable();
- }
- else
- {
- stop_glerror();
- glBindFramebuffer(GL_FRAMEBUFFER, mPreviousFBO);
- sCurFBO = mPreviousFBO;
-
- if (mPreviousFBO)
- {
- glViewport(0, 0, mPreviousResX, mPreviousResY);
- sCurResX = mPreviousResX;
- sCurResY = mPreviousResY;
- }
- else
- {
- glViewport(gGLViewport[0],gGLViewport[1],gGLViewport[2],gGLViewport[3]);
- sCurResX = gGLViewport[2];
- sCurResY = gGLViewport[3];
- }
-
- stop_glerror();
- }
-}
-
-void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
- S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter)
+void LLRenderTarget::flush()
{
- GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE;
-
- LLGLDepthTest depth(write_depth, write_depth);
-
- gGL.flush();
- if (!source.mFBO || !mFBO)
- {
- LL_WARNS() << "Cannot copy framebuffer contents for non FBO render targets." << LL_ENDL;
- return;
- }
-
-
- if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil)
- {
- stop_glerror();
-
- glBindFramebuffer(GL_FRAMEBUFFER, source.mFBO);
- check_framebuffer_status();
- gGL.getTexUnit(0)->bind(this, true);
- stop_glerror();
- glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1);
- stop_glerror();
- glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
- stop_glerror();
- }
- else
- {
- glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO);
- stop_glerror();
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO);
- stop_glerror();
- check_framebuffer_status();
- stop_glerror();
- glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
- stop_glerror();
- glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
- stop_glerror();
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
- stop_glerror();
- glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
- stop_glerror();
- }
-}
+ LL_PROFILE_GPU_ZONE("rt flush");
+ gGL.flush();
+ llassert(mFBO);
+ llassert(sCurFBO == mFBO);
+ llassert(sBoundTarget == this);
+
+ if (mGenerateMipMaps == LLTexUnit::TMG_AUTO) {
+ LL_PROFILE_GPU_ZONE("rt generate mipmaps");
+ bindTexture(0, 0, LLTexUnit::TFO_TRILINEAR);
+ glGenerateMipmap(GL_TEXTURE_2D);
+ }
-//static
-void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
- S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter)
-{
- if (!source.mFBO)
- {
- LL_WARNS() << "Cannot copy framebuffer contents for non FBO render targets." << LL_ENDL;
- return;
- }
-
- {
- GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE;
-
- LLGLDepthTest depth(write_depth, write_depth);
-
- glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO);
- stop_glerror();
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
- stop_glerror();
- check_framebuffer_status();
- stop_glerror();
- glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
- stop_glerror();
- glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
- stop_glerror();
- }
+ 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();
+ }
+ else
+ {
+ sBoundTarget = nullptr;
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ sCurFBO = 0;
+ glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+ sCurResX = gGLViewport[2];
+ sCurResY = gGLViewport[3];
+ }
}
bool LLRenderTarget::isComplete() const
{
- return (!mTex.empty() || mDepth) ? true : false;
+ return (!mTex.empty() || mDepth) ? true : false;
}
void LLRenderTarget::getViewport(S32* viewport)
{
- viewport[0] = 0;
- viewport[1] = 0;
- viewport[2] = mResX;
- viewport[3] = mResY;
+ viewport[0] = 0;
+ viewport[1] = 0;
+ viewport[2] = mResX;
+ viewport[3] = mResY;
}
+bool LLRenderTarget::isBoundInStack() const
+{
+ LLRenderTarget* cur = sBoundTarget;
+ while (cur && cur != this)
+ {
+ cur = cur->mPreviousRT;
+ }
+
+ return cur == this;
+}
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index 584f224dca..9fcea35e3d 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -33,6 +33,8 @@
#include "llrender.h"
/*
+ Wrapper around OpenGL framebuffer objects for use in render-to-texture
+
SAMPLE USAGE:
LLRenderTarget target;
@@ -73,7 +75,12 @@ public:
//allocate resources for rendering
//must be called before use
//multiple calls will release previously allocated resources
- bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0);
+ // resX - width
+ // resY - height
+ // color_fmt - GL color format (e.g. GL_RGB)
+ // depth - if true, allocate a depth buffer
+ // usage - deprecated, should always be TT_TEXTURE
+ bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth = false, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureMipGeneration generateMipMaps = LLTexUnit::TMG_NONE);
//resize existing attachments to use new resolution and color format
// CAUTION: if the GL runs out of memory attempting to resize, this render target will be undefined
@@ -93,7 +100,7 @@ public:
// attachment -- LLImageGL to render into
// use_name -- optional texture name to target instead of attachment->getTexName()
// NOTE: setColorAttachment and releaseColorAttachment cannot be used in conjuction with
- // addColorAttachment, allocateDepth, resize, etc.
+ // addColorAttachment, allocateDepth, resize, etc.
void setColorAttachment(LLImageGL* attachment, LLGLuint use_name = 0);
// detach from current color attachment
@@ -111,14 +118,19 @@ public:
//free any allocated resources
//safe to call redundantly
+ // asserts that this target is not currently bound or present in the RT stack
void release();
//bind target for rendering
//applies appropriate viewport
+ // 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();
//clear render targer, clears depth buffer if present,
//uses scissor rect if in copy-to-texture mode
+ // asserts that this target is currently bound
void clear(U32 mask = 0xFFFFFFFF);
//get applied viewport
@@ -136,7 +148,6 @@ public:
U32 getNumTextures() const;
U32 getDepth(void) const { return mDepth; }
- bool hasStencil() const { return mStencil; }
void bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options = LLTexUnit::TFO_BILINEAR);
@@ -144,21 +155,18 @@ public:
//must be called when rendering is complete
//should be used 1:1 with bindTarget
// call bindTarget once, do all your rendering, call flush once
- // if fetch_depth is TRUE, every effort will be made to copy the depth buffer into
- // the current depth texture. A depth texture will be allocated if needed.
- void flush(bool fetch_depth = FALSE);
-
- void copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
- S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter);
-
- static void copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
- S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter);
+ // 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();
//Returns TRUE if target is ready to be rendered into.
//That is, if the target has been allocated with at least
//one renderable attachment (i.e. color buffer, depth buffer).
bool isComplete() const;
+ // Returns true if this RenderTarget is bound somewhere in the stack
+ bool isBoundInStack() const;
+
static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; }
protected:
@@ -167,14 +175,13 @@ protected:
std::vector<U32> mTex;
std::vector<U32> mInternalFormat;
U32 mFBO;
- U32 mPreviousFBO;
- U32 mPreviousResX;
- U32 mPreviousResY;
-
- U32 mDepth;
- bool mStencil;
- bool mUseDepth;
- bool mRenderDepth;
+ LLRenderTarget* mPreviousRT = nullptr;
+
+ U32 mDepth;
+ bool mUseDepth;
+ LLTexUnit::eTextureMipGeneration mGenerateMipMaps;
+ U32 mMipLevels;
+
LLTexUnit::eTextureType mUsage;
static LLRenderTarget* sBoundTarget;
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index c64f46f38a..22940dc703 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -28,6 +28,10 @@
#include "llshadermgr.h"
#include "llrender.h"
#include "llfile.h"
+#include "lldir.h"
+#include "llsdutil.h"
+#include "llsdserialize.h"
+#include "hbxxh.h"
#if LL_DARWIN
#include "OpenGL/OpenGL.h"
@@ -145,6 +149,11 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
// NOTE order of shader object attaching is VERY IMPORTANT!!!
if (features->calculatesAtmospherics)
{
+ if (!shader->attachVertexObject("environment/srgbF.glsl")) // NOTE -- "F" suffix is superfluous here, there is nothing fragment specific in srgbF
+ {
+ return FALSE;
+ }
+
if (!shader->attachVertexObject("windlight/atmosphericsFuncs.glsl")) {
return FALSE;
}
@@ -171,14 +180,26 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
return FALSE;
}
}
+
+ if (!shader->attachVertexObject("deferred/textureUtilV.glsl"))
+ {
+ return FALSE;
+ }
///////////////////////////////////////
// Attach Fragment Shader Features Next
///////////////////////////////////////
// NOTE order of shader object attaching is VERY IMPORTANT!!!
+ if (features->hasSrgb || features->hasAtmospherics || features->calculatesAtmospherics || features->isDeferred)
+ {
+ if (!shader->attachFragmentObject("environment/srgbF.glsl"))
+ {
+ return FALSE;
+ }
+ }
- if(features->calculatesAtmospherics)
+ if(features->calculatesAtmospherics || features->hasGamma || features->isDeferred)
{
if (features->hasWaterFog)
{
@@ -202,7 +223,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
// we want this BEFORE shadows and AO because those facilities use pos/norm access
- if (features->isDeferred)
+ if (features->isDeferred || features->hasReflectionProbes)
{
if (!shader->attachFragmentObject("deferred/deferredUtil.glsl"))
{
@@ -210,6 +231,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
}
+ if (features->hasScreenSpaceReflections || features->hasReflectionProbes)
+ {
+ if (!shader->attachFragmentObject("deferred/screenSpaceReflUtil.glsl"))
+ {
+ return FALSE;
+ }
+ }
+
if (features->hasShadows)
{
if (!shader->attachFragmentObject("deferred/shadowUtil.glsl"))
@@ -218,6 +247,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
}
+ if (features->hasReflectionProbes)
+ {
+ if (!shader->attachFragmentObject("deferred/reflectionProbeF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+
if (features->hasAmbientOcclusion)
{
if (!shader->attachFragmentObject("deferred/aoUtil.glsl"))
@@ -226,15 +263,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
}
- if (features->hasIndirect)
- {
- if (!shader->attachFragmentObject("deferred/indirect.glsl"))
- {
- return FALSE;
- }
- }
-
- if (features->hasGamma)
+ if (features->hasGamma || features->isDeferred)
{
if (!shader->attachFragmentObject("windlight/gammaF.glsl"))
{
@@ -242,14 +271,6 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
}
- if (features->hasSrgb)
- {
- if (!shader->attachFragmentObject("environment/srgbF.glsl"))
- {
- return FALSE;
- }
- }
-
if (features->encodesNormal)
{
if (!shader->attachFragmentObject("environment/encodeNormF.glsl"))
@@ -258,7 +279,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
}
- if (features->hasAtmospherics)
+ if (features->hasAtmospherics || features->isDeferred)
{
if (!shader->attachFragmentObject("windlight/atmosphericsFuncs.glsl")) {
return FALSE;
@@ -270,17 +291,6 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
}
- if (features->hasTransport)
- {
- if (!shader->attachFragmentObject("windlight/transportF.glsl"))
- {
- return FALSE;
- }
-
- // Test hasFullbright and hasShiny and attach fullbright and
- // fullbright shiny atmos transport if we split them out.
- }
-
// NOTE order of shader object attaching is VERY IMPORTANT!!!
if (features->hasWaterFog)
{
@@ -371,164 +381,6 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
}
- // NOTE order of shader object attaching is VERY IMPORTANT!!!
- else if (features->isFullbright)
- {
-
- if (features->isShiny && features->hasWaterFog)
- {
- if (features->disableTextureIndex)
- {
- if (!shader->attachFragmentObject("lighting/lightFullbrightShinyWaterNonIndexedF.glsl"))
- {
- return FALSE;
- }
- }
- else
- {
- if (!shader->attachFragmentObject("lighting/lightFullbrightShinyWaterF.glsl"))
- {
- return FALSE;
- }
- shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
- }
- }
- else if (features->hasWaterFog)
- {
- if (features->disableTextureIndex)
- {
- if (features->hasAlphaMask)
- {
- if (!shader->attachFragmentObject("lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl"))
- {
- return FALSE;
- }
- }
- else if (!shader->attachFragmentObject("lighting/lightFullbrightWaterNonIndexedF.glsl"))
- {
- return FALSE;
- }
- }
- else
- {
- if (features->hasAlphaMask)
- {
- if (!shader->attachFragmentObject("lighting/lightFullbrightWaterAlphaMaskF.glsl"))
- {
- return FALSE;
- }
- }
- else if (!shader->attachFragmentObject("lighting/lightFullbrightWaterF.glsl"))
- {
- return FALSE;
- }
- shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
- }
- }
-
- else if (features->isShiny)
- {
- if (features->disableTextureIndex)
- {
- if (!shader->attachFragmentObject("lighting/lightFullbrightShinyNonIndexedF.glsl"))
- {
- return FALSE;
- }
- }
- else
- {
- if (!shader->attachFragmentObject("lighting/lightFullbrightShinyF.glsl"))
- {
- return FALSE;
- }
- shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
- }
- }
-
- else
- {
- if (features->disableTextureIndex)
- {
-
- if (features->hasAlphaMask)
- {
- if (!shader->attachFragmentObject("lighting/lightFullbrightNonIndexedAlphaMaskF.glsl"))
- {
- return FALSE;
- }
- }
- else
- {
- if (!shader->attachFragmentObject("lighting/lightFullbrightNonIndexedF.glsl"))
- {
- return FALSE;
- }
- }
- }
- else
- {
- if (features->hasAlphaMask)
- {
- if (!shader->attachFragmentObject("lighting/lightFullbrightAlphaMaskF.glsl"))
- {
- return FALSE;
- }
- }
- else
- {
- if (!shader->attachFragmentObject("lighting/lightFullbrightF.glsl"))
- {
- return FALSE;
- }
- }
- shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
- }
- }
- }
-
- // NOTE order of shader object attaching is VERY IMPORTANT!!!
- else if (features->isShiny)
- {
-
- if (features->hasWaterFog)
- {
- if (features->disableTextureIndex)
- {
- if (!shader->attachFragmentObject("lighting/lightShinyWaterNonIndexedF.glsl"))
- {
- return FALSE;
- }
- }
- else
- {
- if (!shader->attachFragmentObject("lighting/lightShinyWaterF.glsl"))
- {
- return FALSE;
- }
- shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
- }
- }
-
- else
- {
- if (features->disableTextureIndex)
- {
- if (!shader->attachFragmentObject("lighting/lightShinyNonIndexedF.glsl"))
- {
- return FALSE;
- }
- }
- else
- {
- if (!shader->attachFragmentObject("lighting/lightShinyF.glsl"))
- {
- return FALSE;
- }
- shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
- }
- }
- }
-
if (features->mIndexedTextureChannels <= 1)
{
if (!shader->attachVertexObject("objects/nonindexedTextureV.glsl"))
@@ -550,26 +402,60 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
//============================================================================
// Load Shader
-static std::string get_object_log(GLhandleARB ret)
+static std::string get_shader_log(GLuint ret)
{
std::string res;
//get log length
GLint length;
- glGetObjectParameterivARB(ret, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
+ glGetShaderiv(ret, GL_INFO_LOG_LENGTH, &length);
if (length > 0)
{
//the log could be any size, so allocate appropriately
- GLcharARB* log = new GLcharARB[length];
- glGetInfoLogARB(ret, length, &length, log);
+ GLchar* log = new GLchar[length];
+ glGetShaderInfoLog(ret, length, &length, log);
res = std::string((char *)log);
delete[] log;
}
return res;
}
+static std::string get_program_log(GLuint ret)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ std::string res;
+
+ //get log length
+ GLint length;
+ glGetProgramiv(ret, GL_INFO_LOG_LENGTH, &length);
+ if (length > 0)
+ {
+ //the log could be any size, so allocate appropriately
+ GLchar* log = new GLchar[length];
+ glGetProgramInfoLog(ret, length, &length, log);
+ res = std::string((char*)log);
+ delete[] log;
+ }
+ return res;
+}
+
+// get the info log for the given object, be it a shader or program object
+// NOTE: ret MUST be a shader OR a program object
+static std::string get_object_log(GLuint ret)
+{
+ if (glIsProgram(ret))
+ {
+ return get_program_log(ret);
+ }
+ else
+ {
+ llassert(glIsShader(ret));
+ return get_shader_log(ret);
+ }
+}
+
//dump shader source for debugging
-void LLShaderMgr::dumpShaderSource(U32 shader_code_count, GLcharARB** shader_code_text)
+void LLShaderMgr::dumpShaderSource(U32 shader_code_count, GLchar** shader_code_text)
{
char num_str[16]; // U32 = max 10 digits
@@ -584,9 +470,10 @@ void LLShaderMgr::dumpShaderSource(U32 shader_code_count, GLcharARB** shader_cod
LL_CONT << LL_ENDL;
}
-void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns, const std::string& filename)
+void LLShaderMgr::dumpObjectLog(GLuint ret, BOOL warns, const std::string& filename)
{
- std::string log = get_object_log(ret);
+ std::string log;
+ log = get_object_log(ret);
std::string fname = filename;
if (filename.empty())
{
@@ -600,7 +487,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns, const std::string&
}
}
-GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::unordered_map<std::string, std::string>* defines, S32 texture_index_channels)
+GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map<std::string, std::string>* defines, S32 texture_index_channels)
{
// endsure work-around for missing GLSL funcs gets propogated to feature shader files (e.g. srgbF.glsl)
@@ -632,36 +519,57 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
S32 gpu_class;
std::string open_file_name;
- //find the most relevant file
- for (gpu_class = try_gpu_class; gpu_class > 0; gpu_class--)
- { //search from the current gpu class down to class 1 to find the most relevant shader
- std::stringstream fname;
- fname << getShaderDirPrefix();
- fname << gpu_class << "/" << filename;
-
- open_file_name = fname.str();
-
- /*
- Would be awesome, if we didn't have shaders that re-use files
- with different environments to say, add skinning, etc
- can't depend on cached version to have evaluate ifdefs identically...
- if we can define a deterministic hash for the shader based on
- all the inputs, maybe we can save some time here.
- if (mShaderObjects.count(filename) > 0)
+
+#if 0 // WIP -- try to come up with a way to fallback to an error shader without needing debug stubs all over the place in the shader tree
+ if (shader_level == -1)
+ {
+ // use "error" fallback
+ if (type == GL_VERTEX_SHADER)
+ {
+ open_file_name = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders/errorV.glsl");
+ }
+ else
{
- return mShaderObjects[filename];
+ llassert(type == GL_FRAGMENT_SHADER); // type must be vertex or fragment shader
+ open_file_name = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders/errorF.glsl");
}
- */
+ file = LLFile::fopen(open_file_name, "r");
+ }
+ else
+#endif
+ {
+ //find the most relevant file
+ for (gpu_class = try_gpu_class; gpu_class > 0; gpu_class--)
+ { //search from the current gpu class down to class 1 to find the most relevant shader
+ std::stringstream fname;
+ fname << getShaderDirPrefix();
+ fname << gpu_class << "/" << filename;
+
+ open_file_name = fname.str();
+
+ /*
+ Would be awesome, if we didn't have shaders that re-use files
+ with different environments to say, add skinning, etc
+ can't depend on cached version to have evaluate ifdefs identically...
+ if we can define a deterministic hash for the shader based on
+ all the inputs, maybe we can save some time here.
+ if (mShaderObjects.count(filename) > 0)
+ {
+ return mShaderObjects[filename];
+ }
- LL_DEBUGS("ShaderLoading") << "Looking in " << open_file_name << LL_ENDL;
- file = LLFile::fopen(open_file_name, "r"); /* Flawfinder: ignore */
- if (file)
- {
- LL_DEBUGS("ShaderLoading") << "Loading file: " << open_file_name << " (Want class " << gpu_class << ")" << LL_ENDL;
- break; // done
- }
- }
+ */
+
+ LL_DEBUGS("ShaderLoading") << "Looking in " << open_file_name << LL_ENDL;
+ file = LLFile::fopen(open_file_name, "r"); /* Flawfinder: ignore */
+ if (file)
+ {
+ LL_DEBUGS("ShaderLoading") << "Loading file: " << open_file_name << " (Want class " << gpu_class << ")" << LL_ENDL;
+ break; // done
+ }
+ }
+ }
if (file == NULL)
{
@@ -671,9 +579,9 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
//we can't have any lines longer than 1024 characters
//or any shaders longer than 4096 lines... deal - DaveP
- GLcharARB buff[1024];
- GLcharARB *extra_code_text[1024];
- GLcharARB *shader_code_text[4096 + LL_ARRAY_SIZE(extra_code_text)] = { NULL };
+ GLchar buff[1024];
+ GLchar *extra_code_text[1024];
+ GLchar *shader_code_text[4096 + LL_ARRAY_SIZE(extra_code_text)] = { NULL };
GLuint extra_code_count = 0, shader_code_count = 0;
BOOST_STATIC_ASSERT(LL_ARRAY_SIZE(extra_code_text) < LL_ARRAY_SIZE(shader_code_text));
@@ -683,37 +591,21 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
if (major_version == 1 && minor_version < 30)
{
- if (minor_version < 10)
- {
- //should NEVER get here -- if major version is 1 and minor version is less than 10,
- // viewer should never attempt to use shaders, continuing will result in undefined behavior
- LL_ERRS() << "Unsupported GLSL Version." << LL_ENDL;
- }
-
- if (minor_version <= 19)
- {
- shader_code_text[shader_code_count++] = strdup("#version 110\n");
- extra_code_text[extra_code_count++] = strdup("#define ATTRIBUTE attribute\n");
- extra_code_text[extra_code_count++] = strdup("#define VARYING varying\n");
- extra_code_text[extra_code_count++] = strdup("#define VARYING_FLAT varying\n");
- }
- else if (minor_version <= 29)
- {
- //set version to 1.20
- shader_code_text[shader_code_count++] = strdup("#version 120\n");
- extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_120 1\n");
- extra_code_text[extra_code_count++] = strdup("#define FXAA_FAST_PIXEL_OFFSET 0\n");
- extra_code_text[extra_code_count++] = strdup("#define ATTRIBUTE attribute\n");
- extra_code_text[extra_code_count++] = strdup("#define VARYING varying\n");
- extra_code_text[extra_code_count++] = strdup("#define VARYING_FLAT varying\n");
- }
+ llassert(false); // GL 3.1 or later required
}
else
{
if (major_version >= 4)
{
- //set version to 400
- shader_code_text[shader_code_count++] = strdup("#version 400\n");
+ //set version to 400 or 420
+ if (minor_version >= 20)
+ {
+ shader_code_text[shader_code_count++] = strdup("#version 420\n");
+ }
+ else
+ {
+ shader_code_text[shader_code_count++] = strdup("#version 400\n");
+ }
}
else if (major_version == 3)
{
@@ -736,49 +628,29 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
}
else
{
- //set version to 1.30
- shader_code_text[shader_code_count++] = strdup("#version 130\n");
+ //set version to 1.40
+ shader_code_text[shader_code_count++] = strdup("#version 140\n");
//some implementations of GLSL 1.30 require integer precision be explicitly declared
extra_code_text[extra_code_count++] = strdup("precision mediump int;\n");
extra_code_text[extra_code_count++] = strdup("precision highp float;\n");
}
- extra_code_text[extra_code_count++] = strdup("#define DEFINE_GL_FRAGCOLOR 1\n");
extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n");
+ }
- extra_code_text[extra_code_count++] = strdup("#define ATTRIBUTE in\n");
+ // Use alpha float to store bit flags
+ // See: C++: addDeferredAttachment(), shader: frag_data[2]
+ extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_SKIP_ATMOS 0.0 \n"); // atmo kill
+ extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_ATMOS 0.34\n"); // bit 0
+ extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_PBR 0.67\n"); // bit 1
+ extra_code_text[extra_code_count++] = strdup("#define GET_GBUFFER_FLAG(flag) (abs(norm.w-flag)< 0.1)\n");
- if (type == GL_VERTEX_SHADER_ARB)
- { //"varying" state is "out" in a vertex program, "in" in a fragment program
- // ("varying" is deprecated after version 1.20)
- extra_code_text[extra_code_count++] = strdup("#define VARYING out\n");
- extra_code_text[extra_code_count++] = strdup("#define VARYING_FLAT flat out\n");
- }
- else
- {
- extra_code_text[extra_code_count++] = strdup("#define VARYING in\n");
- extra_code_text[extra_code_count++] = strdup("#define VARYING_FLAT flat in\n");
- }
-
- //backwards compatibility with legacy texture lookup syntax
- extra_code_text[extra_code_count++] = strdup("#define texture2D texture\n");
- extra_code_text[extra_code_count++] = strdup("#define textureCube texture\n");
- extra_code_text[extra_code_count++] = strdup("#define texture2DLod textureLod\n");
- extra_code_text[extra_code_count++] = strdup("#define shadow2D(a,b) vec2(texture(a,b))\n");
-
- if (major_version > 1 || minor_version >= 40)
- { //GLSL 1.40 replaces texture2DRect et al with texture
- extra_code_text[extra_code_count++] = strdup("#define texture2DRect texture\n");
- extra_code_text[extra_code_count++] = strdup("#define shadow2DRect(a,b) vec2(texture(a,b))\n");
- }
- }
-
if (defines)
{
- for (std::unordered_map<std::string,std::string>::iterator iter = defines->begin(); iter != defines->end(); ++iter)
+ for (auto iter = defines->begin(); iter != defines->end(); ++iter)
{
std::string define = "#define " + iter->first + " " + iter->second + "\n";
- extra_code_text[extra_code_count++] = (GLcharARB *) strdup(define.c_str());
+ extra_code_text[extra_code_count++] = (GLchar *) strdup(define.c_str());
}
}
@@ -787,7 +659,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
extra_code_text[extra_code_count++] = strdup( "#define IS_AMD_CARD 1\n" );
}
- if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER_ARB)
+ if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER)
{
//use specified number of texture channels for indexed texture rendering
@@ -801,21 +673,21 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
.
uniform sampler2D texN;
- VARYING_FLAT ivec4 vary_texture_index;
+ flat in int vary_texture_index;
vec4 ret = vec4(1,0,1,1);
vec4 diffuseLookup(vec2 texcoord)
{
- switch (vary_texture_index.r))
+ switch (vary_texture_index)
{
- case 0: ret = texture2D(tex0, texcoord); break;
- case 1: ret = texture2D(tex1, texcoord); break;
- case 2: ret = texture2D(tex2, texcoord); break;
+ case 0: ret = texture(tex0, texcoord); break;
+ case 1: ret = texture(tex1, texcoord); break;
+ case 2: ret = texture(tex2, texcoord); break;
.
.
.
- case N: return texture2D(texN, texcoord); break;
+ case N: return texture(texN, texcoord); break;
}
return ret;
@@ -833,7 +705,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
if (texture_index_channels > 1)
{
- extra_code_text[extra_code_count++] = strdup("VARYING_FLAT int vary_texture_index;\n");
+ extra_code_text[extra_code_count++] = strdup("flat in int vary_texture_index;\n");
}
extra_code_text[extra_code_count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n");
@@ -842,7 +714,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
if (texture_index_channels == 1)
{ //don't use flow control, that's silly
- extra_code_text[extra_code_count++] = strdup("return texture2D(tex0, texcoord);\n");
+ extra_code_text[extra_code_count++] = strdup("return texture(tex0, texcoord);\n");
extra_code_text[extra_code_count++] = strdup("}\n");
}
else if (major_version > 1 || minor_version >= 30)
@@ -851,7 +723,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
{ //switches are unreliable on some NVIDIA drivers
for (U32 i = 0; i < texture_index_channels; ++i)
{
- std::string if_string = llformat("\t%sif (vary_texture_index == %d) { return texture2D(tex%d, texcoord); }\n", i > 0 ? "else " : "", i, i);
+ std::string if_string = llformat("\t%sif (vary_texture_index == %d) { return texture(tex%d, texcoord); }\n", i > 0 ? "else " : "", i, i);
extra_code_text[extra_code_count++] = strdup(if_string.c_str());
}
extra_code_text[extra_code_count++] = strdup("\treturn vec4(1,0,1,1);\n");
@@ -866,7 +738,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
//switch body
for (S32 i = 0; i < texture_index_channels; ++i)
{
- std::string case_str = llformat("\t\tcase %d: return texture2D(tex%d, texcoord);\n", i, i);
+ std::string case_str = llformat("\t\tcase %d: return texture(tex%d, texcoord);\n", i, i);
extra_code_text[extra_code_count++] = strdup(case_str.c_str());
}
@@ -892,6 +764,13 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
GLuint out_of_extra_block_counter = 0, start_shader_code = shader_code_count, file_lines_count = 0;
+#define TOUCH_SHADERS 0
+
+#if TOUCH_SHADERS
+ const char* marker = "// touched";
+ bool touched = false;
+#endif
+
while(NULL != fgets((char *)buff, 1024, file)
&& shader_code_count < (LL_ARRAY_SIZE(shader_code_text) - LL_ARRAY_SIZE(extra_code_text)))
{
@@ -899,6 +778,13 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
bool extra_block_area_found = NULL != strstr((const char*)buff, "[EXTRA_CODE_HERE]");
+#if TOUCH_SHADERS
+ if (NULL != strstr((const char*)buff, marker))
+ {
+ touched = true;
+ }
+#endif
+
if(extra_block_area_found && !(flag_extra_block_marker_was_found & flags))
{
if(!(flag_write_to_out_of_extra_block_area & flags))
@@ -927,7 +813,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
}
else
{
- shader_code_text[shader_code_count] = (GLcharARB *)strdup((char *)buff);
+ shader_code_text[shader_code_count] = (GLchar *)strdup((char *)buff);
if(flag_write_to_out_of_extra_block_area & flags)
{
@@ -961,48 +847,71 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
extra_code_count = 0;
}
+#if TOUCH_SHADERS
+ if (!touched)
+ {
+ fprintf(file, "\n%s\n", marker);
+ }
+#endif
+
fclose(file);
//create shader object
- GLhandleARB ret = glCreateShaderObjectARB(type);
+ GLuint ret = glCreateShader(type);
error = glGetError();
if (error != GL_NO_ERROR)
{
- LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShaderObjectARB: " << error << " for file: " << open_file_name << LL_ENDL;
+ LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShader: " << error << " for file: " << open_file_name << LL_ENDL;
+ if (ret)
+ {
+ glDeleteShader(ret); //no longer need handle
+ ret = 0;
+ }
}
//load source
- glShaderSourceARB(ret, shader_code_count, (const GLcharARB**) shader_code_text, NULL);
-
- error = glGetError();
- if (error != GL_NO_ERROR)
+ if (ret)
{
- LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSourceARB: " << error << " for file: " << open_file_name << LL_ENDL;
+ glShaderSource(ret, shader_code_count, (const GLchar**)shader_code_text, NULL);
+
+ error = glGetError();
+ if (error != GL_NO_ERROR)
+ {
+ LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSource: " << error << " for file: " << open_file_name << LL_ENDL;
+ glDeleteShader(ret); //no longer need handle
+ ret = 0;
+ }
}
//compile source
- glCompileShaderARB(ret);
-
- error = glGetError();
- if (error != GL_NO_ERROR)
+ if (ret)
{
- LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShaderARB: " << error << " for file: " << open_file_name << LL_ENDL;
+ glCompileShader(ret);
+
+ error = glGetError();
+ if (error != GL_NO_ERROR)
+ {
+ LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShader: " << error << " for file: " << open_file_name << LL_ENDL;
+ glDeleteShader(ret); //no longer need handle
+ ret = 0;
+ }
}
if (error == GL_NO_ERROR)
{
//check for errors
GLint success = GL_TRUE;
- glGetObjectParameterivARB(ret, GL_OBJECT_COMPILE_STATUS_ARB, &success);
+ glGetShaderiv(ret, GL_COMPILE_STATUS, &success);
error = glGetError();
- if (error != GL_NO_ERROR || success == GL_FALSE)
+ if (error != GL_NO_ERROR || success == GL_FALSE)
{
//an error occured, print log
LL_WARNS("ShaderLoading") << "GLSL Compilation Error:" << LL_ENDL;
dumpObjectLog(ret, TRUE, open_file_name);
dumpShaderSource(shader_code_count, shader_code_text);
+ glDeleteShader(ret); //no longer need handle
ret = 0;
}
}
@@ -1022,10 +931,10 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
if (ret)
{
// Add shader file to map
- if (type == GL_VERTEX_SHADER_ARB) {
+ if (type == GL_VERTEX_SHADER) {
mVertexShaderObjects[filename] = ret;
}
- else if (type == GL_FRAGMENT_SHADER_ARB) {
+ else if (type == GL_FRAGMENT_SHADER) {
mFragmentShaderObjects[filename] = ret;
}
shader_level = try_gpu_class;
@@ -1042,19 +951,29 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
return ret;
}
-BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors)
+BOOL LLShaderMgr::linkProgramObject(GLuint obj, BOOL suppress_errors)
{
//check for errors
- glLinkProgramARB(obj);
- GLint success = GL_TRUE;
- glGetObjectParameterivARB(obj, GL_OBJECT_LINK_STATUS_ARB, &success);
- if (!suppress_errors && success == GL_FALSE)
- {
- //an error occured, print log
- LL_SHADER_LOADING_WARNS() << "GLSL Linker Error:" << LL_ENDL;
- }
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_SHADER("glLinkProgram");
+ glLinkProgram(obj);
+ }
+
+ GLint success = GL_TRUE;
+
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_SHADER("glsl check link status");
+ glGetProgramiv(obj, GL_LINK_STATUS, &success);
+ if (!suppress_errors && success == GL_FALSE)
+ {
+ //an error occured, print log
+ LL_SHADER_LOADING_WARNS() << "GLSL Linker Error:" << LL_ENDL;
+ dumpObjectLog(obj, TRUE, "linker");
+ return success;
+ }
+ }
- std::string log = get_object_log(obj);
+ std::string log = get_program_log(obj);
LLStringUtil::toLower(log);
if (log.find("software") != std::string::npos)
{
@@ -1065,12 +984,12 @@ BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors)
return success;
}
-BOOL LLShaderMgr::validateProgramObject(GLhandleARB obj)
+BOOL LLShaderMgr::validateProgramObject(GLuint obj)
{
//check program validity against current GL
- glValidateProgramARB(obj);
+ glValidateProgram(obj);
GLint success = GL_TRUE;
- glGetObjectParameterivARB(obj, GL_OBJECT_VALIDATE_STATUS_ARB, &success);
+ glGetProgramiv(obj, GL_LINK_STATUS, &success);
if (success == GL_FALSE)
{
LL_SHADER_LOADING_WARNS() << "GLSL program not valid: " << LL_ENDL;
@@ -1084,6 +1003,176 @@ BOOL LLShaderMgr::validateProgramObject(GLhandleARB obj)
return success;
}
+void LLShaderMgr::initShaderCache(bool enabled, const LLUUID& old_cache_version, const LLUUID& current_cache_version)
+{
+ LL_INFOS() << "Initializing shader cache" << LL_ENDL;
+
+ mShaderCacheEnabled = gGLManager.mGLVersion >= 4.09 && enabled;
+
+ if(!mShaderCacheEnabled || mShaderCacheInitialized)
+ return;
+
+ mShaderCacheInitialized = true;
+
+ mShaderCacheDir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "shader_cache");
+ LLFile::mkdir(mShaderCacheDir);
+
+ {
+ std::string meta_out_path = gDirUtilp->add(mShaderCacheDir, "shaderdata.llsd");
+ if (gDirUtilp->fileExists(meta_out_path))
+ {
+ LL_INFOS() << "Loading shader cache metadata" << LL_ENDL;
+
+ llifstream instream(meta_out_path);
+ LLSD in_data;
+ LLSDSerialize::fromNotation(in_data, instream, LLSDSerialize::SIZE_UNLIMITED);
+ instream.close();
+
+ if (old_cache_version == current_cache_version)
+ {
+ for (const auto& data_pair : llsd::inMap(in_data))
+ {
+ ProgramBinaryData binary_info = ProgramBinaryData();
+ binary_info.mBinaryFormat = data_pair.second["binary_format"].asInteger();
+ binary_info.mBinaryLength = data_pair.second["binary_size"].asInteger();
+ binary_info.mLastUsedTime = data_pair.second["last_used"].asReal();
+ mShaderBinaryCache.insert_or_assign(LLUUID(data_pair.first), binary_info);
+ }
+ }
+ else
+ {
+ LL_INFOS() << "Shader cache version mismatch detected. Purging." << LL_ENDL;
+ clearShaderCache();
+ }
+ }
+ }
+}
+
+void LLShaderMgr::clearShaderCache()
+{
+ std::string shader_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "shader_cache");
+ LL_INFOS() << "Removing shader cache at " << shader_cache << LL_ENDL;
+ const std::string mask = "*";
+ gDirUtilp->deleteFilesInDir(shader_cache, mask);
+ mShaderBinaryCache.clear();
+}
+
+void LLShaderMgr::persistShaderCacheMetadata()
+{
+ if(!mShaderCacheEnabled) return;
+
+ LL_INFOS() << "Persisting shader cache metadata to disk" << LL_ENDL;
+
+ LLSD out = LLSD::emptyMap();
+
+ static const F32 LRU_TIME = (60.f * 60.f) * 24.f * 7.f; // 14 days
+ const F32 current_time = LLTimer::getTotalSeconds();
+ for (auto it = mShaderBinaryCache.begin(); it != mShaderBinaryCache.end();)
+ {
+ const ProgramBinaryData& shader_metadata = it->second;
+ if ((shader_metadata.mLastUsedTime + LRU_TIME) < current_time)
+ {
+ std::string shader_path = gDirUtilp->add(mShaderCacheDir, it->first.asString() + ".shaderbin");
+ LLFile::remove(shader_path);
+ it = mShaderBinaryCache.erase(it);
+ }
+ else
+ {
+ LLSD data = LLSD::emptyMap();
+ data["binary_format"] = LLSD::Integer(shader_metadata.mBinaryFormat);
+ data["binary_size"] = LLSD::Integer(shader_metadata.mBinaryLength);
+ data["last_used"] = LLSD::Real(shader_metadata.mLastUsedTime);
+ out[it->first.asString()] = data;
+ ++it;
+ }
+ }
+
+ std::string meta_out_path = gDirUtilp->add(mShaderCacheDir, "shaderdata.llsd");
+ llofstream outstream(meta_out_path);
+ LLSDSerialize::toNotation(out, outstream);
+ outstream.close();
+}
+
+bool LLShaderMgr::loadCachedProgramBinary(LLGLSLShader* shader)
+{
+ if (!mShaderCacheEnabled) return false;
+
+ glProgramParameteri(shader->mProgramObject, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
+
+ auto binary_iter = mShaderBinaryCache.find(shader->mShaderHash);
+ if (binary_iter != mShaderBinaryCache.end())
+ {
+ std::string in_path = gDirUtilp->add(mShaderCacheDir, shader->mShaderHash.asString() + ".shaderbin");
+ auto& shader_info = binary_iter->second;
+ if (shader_info.mBinaryLength > 0)
+ {
+ std::vector<U8> in_data;
+ in_data.resize(shader_info.mBinaryLength);
+
+ LLUniqueFile filep = LLFile::fopen(in_path, "rb");
+ if (filep)
+ {
+ size_t result = fread(in_data.data(), sizeof(U8), in_data.size(), filep);
+ filep.close();
+
+ if (result == in_data.size())
+ {
+ GLenum error = glGetError(); // Clear current error
+ glProgramBinary(shader->mProgramObject, shader_info.mBinaryFormat, in_data.data(), shader_info.mBinaryLength);
+
+ error = glGetError();
+ GLint success = GL_TRUE;
+ glGetProgramiv(shader->mProgramObject, GL_LINK_STATUS, &success);
+ if (error == GL_NO_ERROR && success == GL_TRUE)
+ {
+ binary_iter->second.mLastUsedTime = LLTimer::getTotalSeconds();
+ LL_INFOS() << "Loaded cached binary for shader: " << shader->mName << LL_ENDL;
+ return true;
+ }
+ }
+ }
+ }
+ //an error occured, normally we would print log but in this case it means the shader needs recompiling.
+ LL_INFOS() << "Failed to load cached binary for shader: " << shader->mName << " falling back to compilation" << LL_ENDL;
+ LLFile::remove(in_path);
+ mShaderBinaryCache.erase(binary_iter);
+ }
+ return false;
+}
+
+bool LLShaderMgr::saveCachedProgramBinary(LLGLSLShader* shader)
+{
+ if (!mShaderCacheEnabled) return true;
+
+ ProgramBinaryData binary_info = ProgramBinaryData();
+ glGetProgramiv(shader->mProgramObject, GL_PROGRAM_BINARY_LENGTH, &binary_info.mBinaryLength);
+ if (binary_info.mBinaryLength > 0)
+ {
+ std::vector<U8> program_binary;
+ program_binary.resize(binary_info.mBinaryLength);
+
+ GLenum error = glGetError(); // Clear current error
+ glGetProgramBinary(shader->mProgramObject, program_binary.size() * sizeof(U8), nullptr, &binary_info.mBinaryFormat, program_binary.data());
+ error = glGetError();
+ if (error == GL_NO_ERROR)
+ {
+ std::string out_path = gDirUtilp->add(mShaderCacheDir, shader->mShaderHash.asString() + ".shaderbin");
+ LLUniqueFile outfile = LLFile::fopen(out_path, "wb");
+ if (outfile)
+ {
+ fwrite(program_binary.data(), sizeof(U8), program_binary.size(), outfile);
+ outfile.close();
+
+ binary_info.mLastUsedTime = LLTimer::getTotalSeconds();
+
+ mShaderBinaryCache.insert_or_assign(shader->mShaderHash, binary_info);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
//virtual
void LLShaderMgr::initAttribsAndUniforms()
{
@@ -1108,6 +1197,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("inv_proj");
mReservedUniforms.push_back("modelview_projection_matrix");
mReservedUniforms.push_back("inv_modelview");
+ mReservedUniforms.push_back("identity_matrix");
mReservedUniforms.push_back("normal_matrix");
mReservedUniforms.push_back("texture_matrix0");
mReservedUniforms.push_back("texture_matrix1");
@@ -1115,13 +1205,20 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("texture_matrix3");
mReservedUniforms.push_back("object_plane_s");
mReservedUniforms.push_back("object_plane_t");
- llassert(mReservedUniforms.size() == LLShaderMgr::OBJECT_PLANE_T+1);
+
+ 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_emissive_transform"); // (GLTF)
+
+ llassert(mReservedUniforms.size() == LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM+1);
mReservedUniforms.push_back("viewport");
mReservedUniforms.push_back("light_position");
mReservedUniforms.push_back("light_direction");
mReservedUniforms.push_back("light_attenuation");
+ mReservedUniforms.push_back("light_deferred_attenuation");
mReservedUniforms.push_back("light_diffuse");
mReservedUniforms.push_back("light_ambient");
mReservedUniforms.push_back("light_count");
@@ -1148,22 +1245,31 @@ void LLShaderMgr::initAttribsAndUniforms()
llassert(mReservedUniforms.size() == LLShaderMgr::PROJECTOR_AMBIENT_LOD+1);
mReservedUniforms.push_back("color");
-
+ mReservedUniforms.push_back("emissiveColor");
+ mReservedUniforms.push_back("metallicFactor");
+ mReservedUniforms.push_back("roughnessFactor");
+
mReservedUniforms.push_back("diffuseMap");
mReservedUniforms.push_back("altDiffuseMap");
mReservedUniforms.push_back("specularMap");
+ mReservedUniforms.push_back("emissiveMap");
mReservedUniforms.push_back("bumpMap");
mReservedUniforms.push_back("bumpMap2");
mReservedUniforms.push_back("environmentMap");
+ mReservedUniforms.push_back("sceneMap");
+ mReservedUniforms.push_back("sceneDepth");
+ mReservedUniforms.push_back("reflectionProbes");
+ mReservedUniforms.push_back("irradianceProbes");
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");
+ mReservedUniforms.push_back("sky_hdr_scale");
mReservedUniforms.push_back("blue_horizon");
- mReservedUniforms.push_back("blue_density");
- mReservedUniforms.push_back("haze_horizon");
+ mReservedUniforms.push_back("blue_density");
+ mReservedUniforms.push_back("haze_horizon");
mReservedUniforms.push_back("haze_density");
mReservedUniforms.push_back("cloud_shadow");
mReservedUniforms.push_back("density_multiplier");
@@ -1194,13 +1300,15 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("warmthAmount");
mReservedUniforms.push_back("glowStrength");
mReservedUniforms.push_back("glowDelta");
+ mReservedUniforms.push_back("glowNoiseMap");
- llassert(mReservedUniforms.size() == LLShaderMgr::GLOW_DELTA+1);
+ llassert(mReservedUniforms.size() == LLShaderMgr::GLOW_NOISE_MAP+1);
mReservedUniforms.push_back("minimum_alpha");
mReservedUniforms.push_back("emissive_brightness");
+ // Deferred
mReservedUniforms.push_back("shadow_matrix");
mReservedUniforms.push_back("env_mat");
mReservedUniforms.push_back("shadow_clip");
@@ -1226,7 +1334,19 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("norm_cutoff");
mReservedUniforms.push_back("shadow_target_width");
- llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH+1);
+ llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH + 1);
+
+ mReservedUniforms.push_back("iterationCount");
+ mReservedUniforms.push_back("rayStep");
+ mReservedUniforms.push_back("distanceBias");
+ mReservedUniforms.push_back("depthRejectBias");
+ mReservedUniforms.push_back("glossySampleCount");
+ mReservedUniforms.push_back("noiseSine");
+ mReservedUniforms.push_back("adaptiveStepMultiplier");
+
+ mReservedUniforms.push_back("modelview_delta");
+ mReservedUniforms.push_back("inv_modelview_delta");
+ mReservedUniforms.push_back("cube_snapshot");
mReservedUniforms.push_back("tc_scale");
mReservedUniforms.push_back("rcp_screen_res");
@@ -1256,6 +1376,9 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("positionMap");
mReservedUniforms.push_back("diffuseRect");
mReservedUniforms.push_back("specularRect");
+ mReservedUniforms.push_back("emissiveRect");
+ mReservedUniforms.push_back("exposureMap");
+ mReservedUniforms.push_back("brdfLut");
mReservedUniforms.push_back("noiseMap");
mReservedUniforms.push_back("lightFunc");
mReservedUniforms.push_back("lightMap");
@@ -1281,6 +1404,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("specular");
mReservedUniforms.push_back("lightExp");
mReservedUniforms.push_back("waterFogColor");
+ mReservedUniforms.push_back("waterFogColorLinear");
mReservedUniforms.push_back("waterFogDensity");
mReservedUniforms.push_back("waterFogKS");
mReservedUniforms.push_back("refScale");
@@ -1318,7 +1442,6 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("single_mie_scattering_texture");
mReservedUniforms.push_back("irradiance_texture");
mReservedUniforms.push_back("blend_factor");
- mReservedUniforms.push_back("no_atmo");
mReservedUniforms.push_back("moisture_level");
mReservedUniforms.push_back("droplet_radius");
mReservedUniforms.push_back("ice_level");
@@ -1326,6 +1449,8 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("halo_map");
mReservedUniforms.push_back("moon_brightness");
mReservedUniforms.push_back("cloud_variance");
+ mReservedUniforms.push_back("reflection_probe_ambiance");
+ mReservedUniforms.push_back("max_probe_lod");
mReservedUniforms.push_back("sh_input_r");
mReservedUniforms.push_back("sh_input_g");
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index 67c0d6ab10..ac4b393fb7 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -44,6 +44,7 @@ public:
INVERSE_PROJECTION_MATRIX, // "inv_proj"
MODELVIEW_PROJECTION_MATRIX, // "modelview_projection_matrix"
INVERSE_MODELVIEW_MATRIX, // "inv_modelview"
+ IDENTITY_MATRIX, // "identity_matrix"
NORMAL_MATRIX, // "normal_matrix"
TEXTURE_MATRIX0, // "texture_matrix0"
TEXTURE_MATRIX1, // "texture_matrix1"
@@ -51,10 +52,17 @@ public:
TEXTURE_MATRIX3, // "texture_matrix3"
OBJECT_PLANE_S, // "object_plane_s"
OBJECT_PLANE_T, // "object_plane_t"
+
+ 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_EMISSIVE_TRANSFORM, // "texture_emissive_transform" (GLTF)
+
VIEWPORT, // "viewport"
LIGHT_POSITION, // "light_position"
LIGHT_DIRECTION, // "light_direction"
LIGHT_ATTENUATION, // "light_attenuation"
+ LIGHT_DEFERRED_ATTENUATION, // "light_deferred_attenuation"
LIGHT_DIFFUSE, // "light_diffuse"
LIGHT_AMBIENT, // "light_ambient"
MULTI_LIGHT_COUNT, // "light_count"
@@ -74,18 +82,27 @@ public:
PROJECTOR_LOD, // "proj_lod"
PROJECTOR_AMBIENT_LOD, // "proj_ambient_lod"
DIFFUSE_COLOR, // "color"
+ EMISSIVE_COLOR, // "emissiveColor"
+ METALLIC_FACTOR, // "metallicFactor"
+ ROUGHNESS_FACTOR, // "roughnessFactor"
DIFFUSE_MAP, // "diffuseMap"
ALTERNATE_DIFFUSE_MAP, // "altDiffuseMap"
SPECULAR_MAP, // "specularMap"
+ EMISSIVE_MAP, // "emissiveMap"
BUMP_MAP, // "bumpMap"
BUMP_MAP2, // "bumpMap2"
ENVIRONMENT_MAP, // "environmentMap"
+ SCENE_MAP, // "sceneMap"
+ SCENE_DEPTH, // "sceneDepth"
+ REFLECTION_PROBES, // "reflectionProbes"
+ IRRADIANCE_PROBES, // "irradianceProbes"
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"
+ SKY_HDR_SCALE, // "sky_hdr_scale"
BLUE_HORIZON, // "blue_horizon"
BLUE_DENSITY, // "blue_density"
HAZE_HORIZON, // "haze_horizon"
@@ -114,6 +131,7 @@ public:
GLOW_WARMTH_AMOUNT, // "warmthAmount"
GLOW_STRENGTH, // "glowStrength"
GLOW_DELTA, // "glowDelta"
+ GLOW_NOISE_MAP, // "glowNoiseMap"
MINIMUM_ALPHA, // "minimum_alpha"
EMISSIVE_BRIGHTNESS, // "emissive_brightness"
@@ -143,6 +161,18 @@ public:
DEFERRED_NORM_CUTOFF, // "norm_cutoff"
DEFERRED_SHADOW_TARGET_WIDTH, // "shadow_target_width"
+ DEFERRED_SSR_ITR_COUNT, // "iterationCount"
+ DEFERRED_SSR_RAY_STEP, // "rayStep"
+ DEFERRED_SSR_DIST_BIAS, // "distanceBias"
+ DEFERRED_SSR_REJECT_BIAS, // "depthRejectBias"
+ DEFERRED_SSR_GLOSSY_SAMPLES, // "glossySampleCount"
+ DEFERRED_SSR_NOISE_SINE, // "noiseSine"
+ DEFERRED_SSR_ADAPTIVE_STEP_MULT, // "adaptiveStepMultiplier"
+
+ MODELVIEW_DELTA_MATRIX, // "modelview_delta"
+ INVERSE_MODELVIEW_DELTA_MATRIX, // "inv_modelview_delta"
+ CUBE_SNAPSHOT, // "cube_snapshot"
+
FXAA_TC_SCALE, // "tc_scale"
FXAA_RCP_SCREEN_RES, // "rcp_screen_res"
FXAA_RCP_FRAME_OPT, // "rcp_frame_opt"
@@ -168,6 +198,9 @@ public:
DEFERRED_POSITION, // "positionMap"
DEFERRED_DIFFUSE, // "diffuseRect"
DEFERRED_SPECULAR, // "specularRect"
+ DEFERRED_EMISSIVE, // "emissiveRect"
+ EXPOSURE_MAP, // "exposureMap"
+ DEFERRED_BRDF_LUT, // "brdfLut"
DEFERRED_NOISE, // "noiseMap"
DEFERRED_LIGHTFUNC, // "lightFunc"
DEFERRED_LIGHT, // "lightMap"
@@ -192,6 +225,7 @@ public:
WATER_SPECULAR, // "specular"
WATER_SPECULAR_EXP, // "lightExp"
WATER_FOGCOLOR, // "waterFogColor"
+ WATER_FOGCOLOR_LINEAR, // "waterFogColorLinear"
WATER_FOGDENSITY, // "waterFogDensity"
WATER_FOGKS, // "waterFogKS"
WATER_REFSCALE, // "refScale"
@@ -231,7 +265,6 @@ public:
ILLUMINANCE_TEX, // "irradiance_texture"
BLEND_FACTOR, // "blend_factor"
- NO_ATMO, // "no_atmo"
MOISTURE_LEVEL, // "moisture_level"
DROPLET_RADIUS, // "droplet_radius"
ICE_LEVEL, // "ice_level"
@@ -242,6 +275,8 @@ public:
CLOUD_VARIANCE, // "cloud_variance"
+ REFLECTION_PROBE_AMBIANCE, // "reflection_probe_ambiance"
+ REFLECTION_PROBE_MAX_LOD, // "max_probe_lod"
SH_INPUT_L1R, // "sh_input_r"
SH_INPUT_L1G, // "sh_input_g"
SH_INPUT_L1B, // "sh_input_b"
@@ -260,11 +295,11 @@ public:
virtual void initAttribsAndUniforms(void);
BOOL attachShaderFeatures(LLGLSLShader * shader);
- void dumpObjectLog(GLhandleARB ret, BOOL warns = TRUE, const std::string& filename = "");
- void dumpShaderSource(U32 shader_code_count, GLcharARB** shader_code_text);
- BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE);
- BOOL validateProgramObject(GLhandleARB obj);
- GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::unordered_map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1);
+ void dumpObjectLog(GLuint ret, BOOL warns = TRUE, const std::string& filename = "");
+ void dumpShaderSource(U32 shader_code_count, GLchar** shader_code_text);
+ BOOL linkProgramObject(GLuint obj, BOOL suppress_errors = FALSE);
+ BOOL validateProgramObject(GLuint obj);
+ GLuint loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1);
// Implemented in the application to actually point to the shader directory.
virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual
@@ -272,18 +307,33 @@ public:
// Implemented in the application to actually update out of date uniforms for a particular shader
virtual void updateShaderUniforms(LLGLSLShader * shader) = 0; // Pure Virtual
+ void initShaderCache(bool enabled, const LLUUID& old_cache_version, const LLUUID& current_cache_version);
+ void clearShaderCache();
+ void persistShaderCacheMetadata();
+
+ bool loadCachedProgramBinary(LLGLSLShader* shader);
+ bool saveCachedProgramBinary(LLGLSLShader* shader);
+
public:
// Map of shader names to compiled
- std::map<std::string, GLhandleARB> mVertexShaderObjects;
- std::map<std::string, GLhandleARB> mFragmentShaderObjects;
+ std::map<std::string, GLuint> mVertexShaderObjects;
+ std::map<std::string, GLuint> mFragmentShaderObjects;
//global (reserved slot) shader parameters
std::vector<std::string> mReservedAttribs;
std::vector<std::string> mReservedUniforms;
- //preprocessor definitions (name/value)
- std::map<std::string, std::string> mDefinitions;
+ struct ProgramBinaryData
+ {
+ GLsizei mBinaryLength = 0;
+ GLenum mBinaryFormat = 0;
+ F32 mLastUsedTime = 0.0;
+ };
+ std::map<LLUUID, ProgramBinaryData> mShaderBinaryCache;
+ bool mShaderCacheInitialized = false;
+ bool mShaderCacheEnabled = false;
+ std::string mShaderCacheDir;
protected:
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index be3e6ddff0..b5dda23828 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -62,288 +62,476 @@ U32 wpo2(U32 i)
return r;
}
+struct CompareMappedRegion
+{
+ bool operator()(const LLVertexBuffer::MappedRegion& lhs, const LLVertexBuffer::MappedRegion& rhs)
+ {
+ return lhs.mStart < rhs.mStart;
+ }
+};
-const U32 LL_VBO_BLOCK_SIZE = 2048;
-const U32 LL_VBO_POOL_MAX_SEED_SIZE = 256*1024;
+#define ENABLE_GL_WORK_QUEUE 0
-U32 vbo_block_size(U32 size)
-{ //what block size will fit size?
- U32 mod = size % LL_VBO_BLOCK_SIZE;
- return mod == 0 ? size : size + (LL_VBO_BLOCK_SIZE-mod);
-}
+#if ENABLE_GL_WORK_QUEUE
+
+#define THREAD_COUNT 1
+
+//============================================================================
-U32 vbo_block_index(U32 size)
+// High performance WorkQueue for usage in real-time rendering work
+class GLWorkQueue
{
- return vbo_block_size(size)/LL_VBO_BLOCK_SIZE;
-}
+public:
+ using Work = std::function<void()>;
-const U32 LL_VBO_POOL_SEED_COUNT = vbo_block_index(LL_VBO_POOL_MAX_SEED_SIZE);
+ GLWorkQueue();
+ void post(const Work& value);
-//============================================================================
+ size_t size();
-//static
-LLVBOPool LLVertexBuffer::sStreamVBOPool(GL_STREAM_DRAW_ARB, GL_ARRAY_BUFFER_ARB);
-LLVBOPool LLVertexBuffer::sDynamicVBOPool(GL_DYNAMIC_DRAW_ARB, GL_ARRAY_BUFFER_ARB);
-LLVBOPool LLVertexBuffer::sDynamicCopyVBOPool(GL_DYNAMIC_COPY_ARB, GL_ARRAY_BUFFER_ARB);
-LLVBOPool LLVertexBuffer::sStreamIBOPool(GL_STREAM_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB);
-LLVBOPool LLVertexBuffer::sDynamicIBOPool(GL_DYNAMIC_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB);
-
-U32 LLVBOPool::sBytesPooled = 0;
-U32 LLVBOPool::sIndexBytesPooled = 0;
-U32 LLVBOPool::sNameIdx = 0;
-U32 LLVBOPool::sNamePool[1024];
-
-std::list<U32> LLVertexBuffer::sAvailableVAOName;
-U32 LLVertexBuffer::sCurVAOName = 1;
-
-U32 LLVertexBuffer::sAllocatedIndexBytes = 0;
-U32 LLVertexBuffer::sIndexCount = 0;
-
-U32 LLVertexBuffer::sBindCount = 0;
-U32 LLVertexBuffer::sSetCount = 0;
-S32 LLVertexBuffer::sCount = 0;
-S32 LLVertexBuffer::sGLCount = 0;
-S32 LLVertexBuffer::sMappedCount = 0;
-bool LLVertexBuffer::sDisableVBOMapping = false;
-bool LLVertexBuffer::sEnableVBOs = true;
-U32 LLVertexBuffer::sGLRenderBuffer = 0;
-U32 LLVertexBuffer::sGLRenderArray = 0;
-U32 LLVertexBuffer::sGLRenderIndices = 0;
-U32 LLVertexBuffer::sLastMask = 0;
-bool LLVertexBuffer::sVBOActive = false;
-bool LLVertexBuffer::sIBOActive = false;
-U32 LLVertexBuffer::sAllocatedBytes = 0;
-U32 LLVertexBuffer::sVertexCount = 0;
-bool LLVertexBuffer::sMapped = false;
-bool LLVertexBuffer::sUseStreamDraw = true;
-bool LLVertexBuffer::sUseVAO = false;
-bool LLVertexBuffer::sPreferStreamDraw = false;
+ bool done();
+
+ // Get the next element from the queue
+ Work pop();
+
+ void runOne();
+
+ bool runPending();
+
+ void runUntilClose();
+
+ void close();
+
+ bool isClosed();
+ void syncGL();
-U32 LLVBOPool::genBuffer()
+private:
+ std::mutex mMutex;
+ std::condition_variable mCondition;
+ std::queue<Work> mQueue;
+ bool mClosed = false;
+};
+
+GLWorkQueue::GLWorkQueue()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX
- if (sNameIdx == 0)
- {
- glGenBuffersARB(1024, sNamePool);
- sNameIdx = 1024;
- }
+}
+
+void GLWorkQueue::syncGL()
+{
+ /*if (mSync)
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ glWaitSync(mSync, 0, GL_TIMEOUT_IGNORED);
+ mSync = 0;
+ }*/
+}
- return sNamePool[--sNameIdx];
+size_t GLWorkQueue::size()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mQueue.size();
}
-void LLVBOPool::deleteBuffer(U32 name)
+bool GLWorkQueue::done()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX
- if (gGLManager.mInited)
- {
- LLVertexBuffer::unbind();
+ return size() == 0 && isClosed();
+}
- glBindBufferARB(mType, name);
- glBufferDataARB(mType, 0, NULL, mUsage);
- glBindBufferARB(mType, 0);
+void GLWorkQueue::post(const GLWorkQueue::Work& value)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mQueue.push(std::move(value));
+ }
- glDeleteBuffersARB(1, &name);
- }
+ mCondition.notify_one();
}
+// Get the next element from the queue
+GLWorkQueue::Work GLWorkQueue::pop()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+ // Lock the mutex
+ {
+ std::unique_lock<std::mutex> lock(mMutex);
+
+ // Wait for a new element to become available or for the queue to close
+ {
+ mCondition.wait(lock, [=] { return !mQueue.empty() || mClosed; });
+ }
+ }
+
+ Work ret;
+
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ // Get the next element from the queue
+ if (mQueue.size() > 0)
+ {
+ ret = mQueue.front();
+ mQueue.pop();
+ }
+ else
+ {
+ ret = []() {};
+ }
+ }
+
+ return ret;
+}
-LLVBOPool::LLVBOPool(U32 vboUsage, U32 vboType)
-: mUsage(vboUsage), mType(vboType)
+void GLWorkQueue::runOne()
{
- mMissCount.resize(LL_VBO_POOL_SEED_COUNT);
- std::fill(mMissCount.begin(), mMissCount.end(), 0);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+ Work w = pop();
+ w();
+ //mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
}
-U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed)
+void GLWorkQueue::runUntilClose()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX
- llassert(vbo_block_size(size) == size);
-
- U8* ret = NULL;
+ while (!isClosed())
+ {
+ runOne();
+ }
+}
- U32 i = vbo_block_index(size);
+void GLWorkQueue::close()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mClosed = true;
+ }
- if (mFreeList.size() <= i)
- {
- mFreeList.resize(i+1);
- }
+ mCondition.notify_all();
+}
- if (mFreeList[i].empty() || for_seed)
- {
- //make a new buffer
- name = genBuffer();
-
- glBindBufferARB(mType, name);
-
- if (!for_seed && i < LL_VBO_POOL_SEED_COUNT)
- { //record this miss
- mMissCount[i]++;
- }
+bool GLWorkQueue::isClosed()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mClosed;
+}
- if (mType == GL_ARRAY_BUFFER_ARB)
- {
- LLVertexBuffer::sAllocatedBytes += size;
- }
- else
- {
- LLVertexBuffer::sAllocatedIndexBytes += size;
- }
+#include "llwindow.h"
- if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)
- {
- glBufferDataARB(mType, size, 0, mUsage);
- if (mUsage != GL_DYNAMIC_COPY_ARB)
- { //data will be provided by application
- ret = (U8*) ll_aligned_malloc<64>(size);
- if (!ret)
- {
- LL_ERRS() << "Failed to allocate "<< size << " bytes for LLVBOPool buffer " << name <<"." << LL_NEWLINE
- << "Free list size: " << mFreeList.size() // this happens if we are out of memory so a solution might be to clear some from freelist
- << " Allocated Bytes: " << LLVertexBuffer::sAllocatedBytes
- << " Allocated Index Bytes: " << LLVertexBuffer::sAllocatedIndexBytes
- << " Pooled Bytes: " << sBytesPooled
- << " Pooled Index Bytes: " << sIndexBytesPooled
- << LL_ENDL;
- }
- }
- }
- else
- { //always use a true hint of static draw when allocating non-client-backed buffers
- glBufferDataARB(mType, size, 0, GL_STATIC_DRAW_ARB);
- }
+class LLGLWorkerThread : public LLThread
+{
+public:
+ LLGLWorkerThread(const std::string& name, GLWorkQueue* queue, LLWindow* window)
+ : LLThread(name)
+ {
+ mWindow = window;
+ mContext = mWindow->createSharedContext();
+ mQueue = queue;
+ }
- glBindBufferARB(mType, 0);
+ void run() override
+ {
+ mWindow->makeContextCurrent(mContext);
+ gGL.init(false);
+ mQueue->runUntilClose();
+ gGL.shutdown();
+ mWindow->destroySharedContext(mContext);
+ }
- if (for_seed)
- { //put into pool for future use
- llassert(mFreeList.size() > i);
+ GLWorkQueue* mQueue;
+ LLWindow* mWindow;
+ void* mContext = nullptr;
+};
- Record rec;
- rec.mGLName = name;
- rec.mClientData = ret;
-
- if (mType == GL_ARRAY_BUFFER_ARB)
- {
- sBytesPooled += size;
- }
- else
- {
- sIndexBytesPooled += size;
- }
- mFreeList[i].push_back(rec);
- }
- }
- else
- {
- name = mFreeList[i].front().mGLName;
- ret = mFreeList[i].front().mClientData;
- if (mType == GL_ARRAY_BUFFER_ARB)
- {
- sBytesPooled -= size;
- }
- else
- {
- sIndexBytesPooled -= size;
- }
+static LLGLWorkerThread* sVBOThread[THREAD_COUNT];
+static GLWorkQueue* sQueue = nullptr;
- mFreeList[i].pop_front();
- }
+#endif
- return ret;
-}
+//============================================================================
+// Pool of reusable VertexBuffer state
-void LLVBOPool::release(U32 name, U8* buffer, U32 size)
+// batch calls to glGenBuffers
+static GLuint gen_buffer()
{
- llassert(vbo_block_size(size) == size);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
- deleteBuffer(name);
- ll_aligned_free_fallback((U8*) buffer);
+ GLuint ret = 0;
+ constexpr U32 pool_size = 4096;
- if (mType == GL_ARRAY_BUFFER_ARB)
- {
- LLVertexBuffer::sAllocatedBytes -= size;
- }
- else
- {
- LLVertexBuffer::sAllocatedIndexBytes -= size;
- }
+ thread_local static GLuint sNamePool[pool_size];
+ thread_local static U32 sIndex = 0;
+
+ if (sIndex == 0)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("gen buffer");
+ sIndex = pool_size;
+ if (!gGLManager.mIsAMD)
+ {
+ glGenBuffers(pool_size, sNamePool);
+ }
+ else
+ { // work around for AMD driver bug
+ for (U32 i = 0; i < pool_size; ++i)
+ {
+ glGenBuffers(1, sNamePool + i);
+ }
+ }
+ }
+
+ ret = sNamePool[--sIndex];
+ return ret;
}
-void LLVBOPool::seedPool()
+#define ANALYZE_VBO_POOL 0
+
+class LLVBOPool
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX
- U32 dummy_name = 0;
+public:
+ typedef std::chrono::steady_clock::time_point Time;
- if (mFreeList.size() < LL_VBO_POOL_SEED_COUNT)
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("VBOPool Resize");
- mFreeList.resize(LL_VBO_POOL_SEED_COUNT);
- }
+ struct Entry
+ {
+ U8* mData;
+ GLuint mGLName;
+ Time mAge;
+ };
- for (U32 i = 0; i < LL_VBO_POOL_SEED_COUNT; i++)
- {
- if (mMissCount[i] > mFreeList[i].size())
- {
- U32 size = i*LL_VBO_BLOCK_SIZE;
-
- S32 count = mMissCount[i] - mFreeList[i].size();
- for (U32 j = 0; j < count; ++j)
- {
- allocate(dummy_name, size, true);
- }
- }
- }
-}
+ ~LLVBOPool()
+ {
+ clear();
+ }
+ typedef std::unordered_map<U32, std::list<Entry>> Pool;
+ Pool mVBOPool;
+ Pool mIBOPool;
-void LLVBOPool::cleanup()
-{
- U32 size = LL_VBO_BLOCK_SIZE;
+ U32 mTouchCount = 0;
- for (U32 i = 0; i < mFreeList.size(); ++i)
- {
- record_list_t& l = mFreeList[i];
+ U64 mDistributed = 0;
+ U64 mAllocated = 0;
+ U64 mReserved = 0;
+ U32 mMisses = 0;
+ U32 mHits = 0;
- while (!l.empty())
- {
- Record& r = l.front();
+ U64 getVramBytesUsed()
+ {
+ return mAllocated + mReserved;
+ }
- deleteBuffer(r.mGLName);
-
- if (r.mClientData)
- {
- ll_aligned_free<64>((void*) r.mClientData);
- }
+ // increase the size to some common value (e.g. a power of two) to increase hit rate
+ void adjustSize(U32& size)
+ {
+ // size = nhpo2(size); // (193/303)/580 MB (distributed/allocated)/reserved in VBO Pool. Overhead: 66 percent. Hit rate: 77 percent
- l.pop_front();
+ //(245/276)/385 MB (distributed/allocated)/reserved in VBO Pool. Overhead: 57 percent. Hit rate: 69 percent
+ //(187/209)/397 MB (distributed/allocated)/reserved in VBO Pool. Overhead: 112 percent. Hit rate: 76 percent
+ U32 block_size = llmax(nhpo2(size) / 8, (U32) 16);
+ size += block_size - (size % block_size);
+ }
- if (mType == GL_ARRAY_BUFFER_ARB)
- {
- sBytesPooled -= size;
- LLVertexBuffer::sAllocatedBytes -= size;
- }
- else
- {
- sIndexBytesPooled -= size;
- LLVertexBuffer::sAllocatedIndexBytes -= size;
- }
- }
+ void allocate(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(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
+
+ mDistributed += size;
+ adjustSize(size);
+ mAllocated += size;
+
+ auto& pool = type == GL_ELEMENT_ARRAY_BUFFER ? mIBOPool : mVBOPool;
+
+ Pool::iterator iter = pool.find(size);
+ if (iter == pool.end())
+ { // cache miss, allocate a new buffer
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vbo pool miss");
+ LL_PROFILE_GPU_ZONE("vbo alloc");
+
+ mMisses++;
+ name = gen_buffer();
+ glBindBuffer(type, name);
+ glBufferData(type, size, nullptr, GL_DYNAMIC_DRAW);
+ if (type == GL_ELEMENT_ARRAY_BUFFER)
+ {
+ LLVertexBuffer::sGLRenderIndices = name;
+ }
+ else
+ {
+ LLVertexBuffer::sGLRenderBuffer = name;
+ }
+
+ data = (U8*)ll_aligned_malloc_16(size);
+ }
+ else
+ {
+ mHits++;
+ llassert(mReserved >= size); // assert if accounting gets messed up
+ mReserved -= size;
+
+ std::list<Entry>& entries = iter->second;
+ Entry& entry = entries.back();
+ name = entry.mGLName;
+ data = entry.mData;
+
+ entries.pop_back();
+ if (entries.empty())
+ {
+ pool.erase(iter);
+ }
+ }
- size += LL_VBO_BLOCK_SIZE;
- }
+ clean();
+ }
+
+ 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);
+ llassert(name != 0);
+ llassert(data != nullptr);
+
+ clean();
+
+ llassert(mDistributed >= size);
+ mDistributed -= size;
+ adjustSize(size);
+ llassert(mAllocated >= size);
+ mAllocated -= size;
+ mReserved += size;
- //reset miss counts
- std::fill(mMissCount.begin(), mMissCount.end(), 0);
+ auto& pool = type == GL_ELEMENT_ARRAY_BUFFER ? mIBOPool : mVBOPool;
+
+ Pool::iterator iter = pool.find(size);
+
+ if (iter == pool.end())
+ {
+ std::list<Entry> newlist;
+ newlist.push_front({ data, name, std::chrono::steady_clock::now() });
+ pool[size] = newlist;
+ }
+ else
+ {
+ iter->second.push_front({ data, name, std::chrono::steady_clock::now() });
+ }
+
+ }
+
+ // clean periodically (clean gets called for every alloc/free)
+ void clean()
+ {
+ mTouchCount++;
+ if (mTouchCount < 1024) // clean every 1k touches
+ {
+ return;
+ }
+ mTouchCount = 0;
+
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
+
+ std::unordered_map<U32, std::list<Entry>>* pools[] = { &mVBOPool, &mIBOPool };
+
+ using namespace std::chrono_literals;
+
+ Time cutoff = std::chrono::steady_clock::now() - 5s;
+
+ for (auto* pool : pools)
+ {
+ for (Pool::iterator iter = pool->begin(); iter != pool->end(); )
+ {
+ auto& entries = iter->second;
+
+ while (!entries.empty() && entries.back().mAge < cutoff)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vbo cache timeout");
+ auto& entry = entries.back();
+ ll_aligned_free_16(entry.mData);
+ glDeleteBuffers(1, &entry.mGLName);
+ llassert(mReserved >= iter->first);
+ mReserved -= iter->first;
+ entries.pop_back();
+
+ }
+
+ if (entries.empty())
+ {
+ iter = pool->erase(iter);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+ }
+
+#if 0
+ LL_INFOS() << llformat("(%d/%d)/%d MB (distributed/allocated)/total in VBO Pool. Overhead: %d percent. Hit rate: %d percent",
+ mDistributed / 1000000,
+ mAllocated / 1000000,
+ (mAllocated + mReserved) / 1000000, // total bytes
+ ((mAllocated+mReserved-mDistributed)*100)/llmax(mDistributed, (U64) 1), // overhead percent
+ (mHits*100)/llmax(mMisses+mHits, (U32)1)) // hit rate percent
+ << LL_ENDL;
+#endif
+ }
+
+ void clear()
+ {
+ for (auto& entries : mIBOPool)
+ {
+ for (auto& entry : entries.second)
+ {
+ ll_aligned_free_16(entry.mData);
+ glDeleteBuffers(1, &entry.mGLName);
+ }
+ }
+
+ for (auto& entries : mVBOPool)
+ {
+ for (auto& entry : entries.second)
+ {
+ ll_aligned_free_16(entry.mData);
+ glDeleteBuffers(1, &entry.mGLName);
+ }
+ }
+
+ mReserved = 0;
+
+ mIBOPool.clear();
+ mVBOPool.clear();
+ }
+
+
+};
+
+static LLVBOPool* sVBOPool = nullptr;
+
+//static
+U64 LLVertexBuffer::getBytesAllocated()
+{
+ return sVBOPool ? sVBOPool->getVramBytesUsed() : 0;
}
+//============================================================================
+//
+//static
+U32 LLVertexBuffer::sGLRenderBuffer = 0;
+U32 LLVertexBuffer::sGLRenderIndices = 0;
+U32 LLVertexBuffer::sLastMask = 0;
+U32 LLVertexBuffer::sVertexCount = 0;
+
//NOTE: each component must be AT LEAST 4 bytes in size to avoid a performance penalty on AMD hardware
-const S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] =
+const U32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] =
{
sizeof(LLVector4), // TYPE_VERTEX,
sizeof(LLVector4), // TYPE_NORMAL,
@@ -392,79 +580,34 @@ const U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] =
};
//static
-U32 LLVertexBuffer::getVAOName()
-{
- U32 ret = 0;
-
- if (!sAvailableVAOName.empty())
- {
- ret = sAvailableVAOName.front();
- sAvailableVAOName.pop_front();
- }
- else
- {
-#ifdef GL_ARB_vertex_array_object
- glGenVertexArrays(1, &ret);
-#endif
- }
-
- return ret;
-}
-
-//static
-void LLVertexBuffer::releaseVAOName(U32 name)
-{
- sAvailableVAOName.push_back(name);
-}
-
-
-//static
-void LLVertexBuffer::seedPools()
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX
- sStreamVBOPool.seedPool();
- sDynamicVBOPool.seedPool();
- sDynamicCopyVBOPool.seedPool();
- sStreamIBOPool.seedPool();
- sDynamicIBOPool.seedPool();
-}
-
-//static
void LLVertexBuffer::setupClientArrays(U32 data_mask)
{
- if (sLastMask != data_mask)
- {
+ if (sLastMask != data_mask)
+ {
+ for (U32 i = 0; i < TYPE_MAX; ++i)
+ {
+ S32 loc = i;
- if (gGLManager.mGLSLVersionMajor < 2 && gGLManager.mGLSLVersionMinor < 30)
- {
- //make sure texture index is disabled
- data_mask = data_mask & ~MAP_TEXTURE_INDEX;
- }
+ U32 mask = 1 << i;
- for (U32 i = 0; i < TYPE_MAX; ++i)
- {
- S32 loc = i;
-
- U32 mask = 1 << i;
-
- if (sLastMask & (1 << i))
- { //was enabled
- if (!(data_mask & mask))
- { //needs to be disabled
- glDisableVertexAttribArrayARB(loc);
- }
- }
- else
- { //was disabled
- if (data_mask & mask)
- { //needs to be enabled
- glEnableVertexAttribArrayARB(loc);
- }
- }
- }
-
- sLastMask = data_mask;
- }
+ if (sLastMask & (1 << i))
+ { //was enabled
+ if (!(data_mask & mask))
+ { //needs to be disabled
+ glDisableVertexAttribArray(loc);
+ }
+ }
+ else
+ { //was disabled
+ if (data_mask & mask)
+ { //needs to be enabled
+ glEnableVertexAttribArray(loc);
+ }
+ }
+ }
+ }
+
+ sLastMask = data_mask;
}
//static
@@ -481,7 +624,7 @@ void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos)
}
//static
-void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp)
+void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, U32 num_indices, const U16* indicesp)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
llassert(LLGLSLShader::sCurBoundShaderPtr != NULL);
@@ -514,13 +657,18 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto
U16 idx = indicesp[i];
gGL.vertex3fv(pos[idx].getF32ptr());
}
- }
+}
gGL.end();
gGL.flush();
}
-void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const
+bool LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const
{
+ if (!gDebugGL)
+ {
+ return true;
+ }
+
llassert(start < (U32)mNumVerts);
llassert(end < (U32)mNumVerts);
@@ -538,9 +686,8 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of
LL_ERRS() << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << LL_ENDL;
}
- if (gDebugGL && !useVBOs())
{
- U16* idx = ((U16*) getIndicesPointer())+indices_offset;
+ U16* idx = (U16*) mMappedIndexData+indices_offset;
for (U32 i = 0; i < count; ++i)
{
llassert(idx[i] >= start);
@@ -552,234 +699,93 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of
}
}
+ LLVector4a* v = (LLVector4a*)mMappedData;
+
+ for (U32 i = start; i <= end; ++i)
+ {
+ if (!v->isFinite3())
+ {
+ LL_ERRS() << "Non-finite vertex position data detected." << LL_ENDL;
+ }
+ }
+
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
if (shader && shader->mFeatures.mIndexedTextureChannels > 1)
{
- LLStrider<LLVector4a> v;
- //hack to get non-const reference
- LLVertexBuffer* vb = (LLVertexBuffer*) this;
- vb->getVertexStrider(v);
-
+ LLVector4a* v = (LLVector4a*) mMappedData;
+
for (U32 i = start; i < end; i++)
{
- S32 idx = (S32) (v[i][3]+0.25f);
- llassert(idx >= 0);
- if (idx < 0 || idx >= shader->mFeatures.mIndexedTextureChannels)
+ U32 idx = (U32) (v[i][3]+0.25f);
+ if (idx >= shader->mFeatures.mIndexedTextureChannels)
{
LL_ERRS() << "Bad texture index found in vertex data stream." << LL_ENDL;
}
}
}
}
-}
-
-void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
-{
- validateRange(start, end, count, indices_offset);
- mMappable = false;
- gGL.syncMatrices();
-
- llassert(mNumVerts >= 0);
- llassert(LLGLSLShader::sCurBoundShaderPtr != NULL);
-
- if (mGLArray)
- {
- if (mGLArray != sGLRenderArray)
- {
- LL_ERRS() << "Wrong vertex array bound." << LL_ENDL;
- }
- }
- else
- {
- if (mGLIndices != sGLRenderIndices)
- {
- LL_ERRS() << "Wrong index buffer bound." << LL_ENDL;
- }
-
- if (mGLBuffer != sGLRenderBuffer)
- {
- LL_ERRS() << "Wrong vertex buffer bound." << LL_ENDL;
- }
- }
-
- if (gDebugGL && !mGLArray && useVBOs())
- {
- GLint elem = 0;
- glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &elem);
- if (elem != mGLIndices)
- {
- LL_ERRS() << "Wrong index buffer bound!" << LL_ENDL;
- }
- }
-
- if (mode >= LLRender::NUM_MODES)
- {
- LL_ERRS() << "Invalid draw mode: " << mode << LL_ENDL;
- return;
- }
-
- U16* idx = ((U16*) getIndicesPointer())+indices_offset;
-
- stop_glerror();
- LLGLSLShader::startProfile();
- LL_PROFILER_GPU_ZONEC( "gl.DrawRangeElements", 0xFFFF00 )
- glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT,
- idx);
- LLGLSLShader::stopProfile(count, mode);
- stop_glerror();
-
-
+ return true;
+}
- placeFence();
+#ifdef LL_PROFILER_ENABLE_RENDER_DOC
+void LLVertexBuffer::setLabel(const char* label) {
+ LL_LABEL_OBJECT_GL(GL_BUFFER, mGLBuffer, strlen(label), label);
}
+#endif
-void LLVertexBuffer::drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
+void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
{
- mMappable = false;
+ llassert(validateRange(start, end, count, indices_offset));
+ llassert(mGLBuffer == sGLRenderBuffer);
+ llassert(mGLIndices == sGLRenderIndices);
gGL.syncMatrices();
-
- U16* idx = ((U16*)getIndicesPointer()) + indices_offset;
-
- LL_PROFILER_GPU_ZONEC("gl.DrawRangeElements", 0xFFFF00)
- glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT,
- idx);
+ glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT,
+ (GLvoid*) (indices_offset * sizeof(U16)));
}
void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
{
- llassert(LLGLSLShader::sCurBoundShaderPtr != NULL);
- mMappable = false;
- gGL.syncMatrices();
-
- llassert(mNumIndices >= 0);
- if (indices_offset >= (U32) mNumIndices ||
- indices_offset + count > (U32) mNumIndices)
- {
- LL_ERRS() << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << LL_ENDL;
- }
-
- if (mGLArray)
- {
- if (mGLArray != sGLRenderArray)
- {
- LL_ERRS() << "Wrong vertex array bound." << LL_ENDL;
- }
- }
- else
- {
- if (mGLIndices != sGLRenderIndices)
- {
- LL_ERRS() << "Wrong index buffer bound." << LL_ENDL;
- }
-
- if (mGLBuffer != sGLRenderBuffer)
- {
- LL_ERRS() << "Wrong vertex buffer bound." << LL_ENDL;
- }
- }
-
- if (mode >= LLRender::NUM_MODES)
- {
- LL_ERRS() << "Invalid draw mode: " << mode << LL_ENDL;
- return;
- }
-
- stop_glerror();
- LLGLSLShader::startProfile();
- LL_PROFILER_GPU_ZONEC( "gl.DrawElements", 0xA0FFA0 )
- glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT,
- ((U16*) getIndicesPointer()) + indices_offset);
- LLGLSLShader::stopProfile(count, mode);
- stop_glerror();
- placeFence();
+ drawRange(mode, 0, mNumVerts-1, count, indices_offset);
}
void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
- llassert(LLGLSLShader::sCurBoundShaderPtr != NULL);
- mMappable = false;
+ llassert(first + count <= mNumVerts);
+ llassert(mGLBuffer == sGLRenderBuffer);
+ llassert(mGLIndices == sGLRenderIndices);
+
gGL.syncMatrices();
+ glDrawArrays(sGLMode[mode], first, count);
+}
-#ifndef LL_RELEASE_FOR_DOWNLOAD
- llassert(mNumVerts >= 0);
- if (first >= (U32)mNumVerts ||
- first + count > (U32)mNumVerts)
- {
- LL_ERRS() << "Bad vertex buffer draw range: [" << first << ", " << first + count << "]" << LL_ENDL;
- }
+//static
+void LLVertexBuffer::initClass(LLWindow* window)
+{
+ llassert(sVBOPool == nullptr);
+ sVBOPool = new LLVBOPool();
- if (mGLArray)
- {
- if (mGLArray != sGLRenderArray)
- {
- LL_ERRS() << "Wrong vertex array bound." << LL_ENDL;
- }
- }
- else
- {
- if (mGLBuffer != sGLRenderBuffer || useVBOs() != sVBOActive)
- {
- LL_ERRS() << "Wrong vertex buffer bound." << LL_ENDL;
- }
- }
+#if ENABLE_GL_WORK_QUEUE
+ sQueue = new GLWorkQueue();
- if (mode >= LLRender::NUM_MODES)
+ for (int i = 0; i < THREAD_COUNT; ++i)
{
- LL_ERRS() << "Invalid draw mode: " << mode << LL_ENDL;
- return;
+ sVBOThread[i] = new LLGLWorkerThread("VBO Worker", sQueue, window);
+ sVBOThread[i]->start();
}
#endif
-
- LLGLSLShader::startProfile();
- {
- LL_PROFILER_GPU_ZONEC("gl.DrawArrays", 0xFF4040)
- glDrawArrays(sGLMode[mode], first, count);
- }
- LLGLSLShader::stopProfile(count, mode);
-
- stop_glerror();
- placeFence();
-}
-
-//static
-void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping)
-{
- sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject;
- sDisableVBOMapping = sEnableVBOs && no_vbo_mapping;
}
//static
void LLVertexBuffer::unbind()
{
- if (sGLRenderArray)
- {
-#if GL_ARB_vertex_array_object
- glBindVertexArray(0);
-#endif
- sGLRenderArray = 0;
- sGLRenderIndices = 0;
- sIBOActive = false;
- }
-
- if (sVBOActive)
- {
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- sVBOActive = false;
- }
- if (sIBOActive)
- {
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
- sIBOActive = false;
- }
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
sGLRenderBuffer = 0;
sGLRenderIndices = 0;
-
- setupClientArrays(0);
}
//static
@@ -787,98 +793,41 @@ void LLVertexBuffer::cleanupClass()
{
unbind();
- sStreamIBOPool.cleanup();
- sDynamicIBOPool.cleanup();
- sStreamVBOPool.cleanup();
- sDynamicVBOPool.cleanup();
- sDynamicCopyVBOPool.cleanup();
-}
+ delete sVBOPool;
+ sVBOPool = nullptr;
-//----------------------------------------------------------------------------
-
-S32 LLVertexBuffer::determineUsage(S32 usage)
-{
- S32 ret_usage = usage;
+#if ENABLE_GL_WORK_QUEUE
+ sQueue->close();
+ for (int i = 0; i < THREAD_COUNT; ++i)
+ {
+ sVBOThread[i]->shutdown();
+ delete sVBOThread[i];
+ sVBOThread[i] = nullptr;
+ }
- if (!sEnableVBOs)
- {
- ret_usage = 0;
- }
-
- if (ret_usage == GL_STREAM_DRAW_ARB && !sUseStreamDraw)
- {
- ret_usage = 0;
- }
-
- if (ret_usage == GL_DYNAMIC_DRAW_ARB && sPreferStreamDraw)
- {
- ret_usage = GL_STREAM_DRAW_ARB;
- }
-
- if (ret_usage == 0 && LLRender::sGLCoreProfile)
- { //MUST use VBOs for all rendering
- ret_usage = GL_STREAM_DRAW_ARB;
- }
-
- if (ret_usage && ret_usage != GL_STREAM_DRAW_ARB)
- { //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default
- if (ret_usage != GL_DYNAMIC_COPY_ARB)
- {
- if (sDisableVBOMapping)
- { //always use stream draw if VBO mapping is disabled
- ret_usage = GL_STREAM_DRAW_ARB;
- }
- else
- {
- ret_usage = GL_DYNAMIC_DRAW_ARB;
- }
- }
- }
-
- return ret_usage;
+ delete sQueue;
+ sQueue = nullptr;
+#endif
}
-LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage)
-: LLRefCount(),
-
- mNumVerts(0),
- mNumIndices(0),
- mAlignedOffset(0),
- mAlignedIndexOffset(0),
- mSize(0),
- mIndicesSize(0),
- mTypeMask(typemask),
- mUsage(LLVertexBuffer::determineUsage(usage)),
- mGLBuffer(0),
- mGLIndices(0),
- mGLArray(0),
- mMappedData(NULL),
- mMappedIndexData(NULL),
- mMappedDataUsingVBOs(false),
- mMappedIndexDataUsingVBOs(false),
- mVertexLocked(false),
- mIndexLocked(false),
- mFinal(false),
- mEmpty(true),
- mMappable(false),
- mFence(NULL)
-{
- mMappable = (mUsage == GL_DYNAMIC_DRAW_ARB && !sDisableVBOMapping);
+//----------------------------------------------------------------------------
+LLVertexBuffer::LLVertexBuffer(U32 typemask)
+: LLRefCount(),
+ mTypeMask(typemask)
+{
//zero out offsets
for (U32 i = 0; i < TYPE_MAX; i++)
{
mOffsets[i] = 0;
}
-
- sCount++;
}
//static
-S32 LLVertexBuffer::calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices)
+U32 LLVertexBuffer::calcOffsets(const U32& typemask, U32* offsets, U32 num_vertices)
{
- S32 offset = 0;
- for (S32 i=0; i<TYPE_TEXTURE_INDEX; i++)
+ U32 offset = 0;
+ for (U32 i=0; i<TYPE_TEXTURE_INDEX; i++)
{
U32 mask = 1<<i;
if (typemask & mask)
@@ -894,14 +843,14 @@ S32 LLVertexBuffer::calcOffsets(const U32& typemask, S32* offsets, S32 num_verti
offsets[TYPE_TEXTURE_INDEX] = offsets[TYPE_VERTEX] + 12;
- return offset+16;
+ return offset;
}
//static
-S32 LLVertexBuffer::calcVertexSize(const U32& typemask)
+U32 LLVertexBuffer::calcVertexSize(const U32& typemask)
{
- S32 size = 0;
- for (S32 i = 0; i < TYPE_TEXTURE_INDEX; i++)
+ U32 size = 0;
+ for (U32 i = 0; i < TYPE_TEXTURE_INDEX; i++)
{
U32 mask = 1<<i;
if (typemask & mask)
@@ -913,11 +862,6 @@ S32 LLVertexBuffer::calcVertexSize(const U32& typemask)
return size;
}
-S32 LLVertexBuffer::getSize() const
-{
- return mSize;
-}
-
// protected, use unref()
//virtual
LLVertexBuffer::~LLVertexBuffer()
@@ -925,27 +869,6 @@ LLVertexBuffer::~LLVertexBuffer()
destroyGLBuffer();
destroyGLIndices();
- if (mGLArray)
- {
-#if GL_ARB_vertex_array_object
- releaseVAOName(mGLArray);
-#endif
- }
-
- sCount--;
-
- if (mFence)
- {
- // Sanity check. We have weird crashes in this destructor (on delete). Yet mFence is disabled.
- // TODO: mFence was added in scope of SH-2038, but was never enabled, consider removing mFence.
- LL_ERRS() << "LLVertexBuffer destruction failed" << LL_ENDL;
- delete mFence;
- mFence = NULL;
- }
-
- sVertexCount -= mNumVerts;
- sIndexCount -= mNumIndices;
-
if (mMappedData)
{
LL_ERRS() << "Failed to clear vertex buffer's vertices" << LL_ENDL;
@@ -956,101 +879,37 @@ LLVertexBuffer::~LLVertexBuffer()
}
};
-void LLVertexBuffer::placeFence() const
-{
- /*if (!mFence && useVBOs())
- {
- if (gGLManager.mHasSync)
- {
- mFence = new LLGLSyncFence();
- }
- }
-
- if (mFence)
- {
- mFence->placeFence();
- }*/
-}
-
-void LLVertexBuffer::waitFence() const
-{
- /*if (mFence)
- {
- mFence->wait();
- }*/
-}
-
//----------------------------------------------------------------------------
void LLVertexBuffer::genBuffer(U32 size)
{
- mSize = vbo_block_size(size);
-
- if (mUsage == GL_STREAM_DRAW_ARB)
- {
- mMappedData = sStreamVBOPool.allocate(mGLBuffer, mSize);
- }
- else if (mUsage == GL_DYNAMIC_DRAW_ARB)
- {
- mMappedData = sDynamicVBOPool.allocate(mGLBuffer, mSize);
- }
- else
- {
- mMappedData = sDynamicCopyVBOPool.allocate(mGLBuffer, mSize);
- }
-
-
- sGLCount++;
-}
-
-void LLVertexBuffer::genIndices(U32 size)
-{
- mIndicesSize = vbo_block_size(size);
-
- if (mUsage == GL_STREAM_DRAW_ARB)
- {
- mMappedIndexData = sStreamIBOPool.allocate(mGLIndices, mIndicesSize);
- }
- else
- {
- mMappedIndexData = sDynamicIBOPool.allocate(mGLIndices, mIndicesSize);
- }
-
- sGLCount++;
-}
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
+ llassert(sVBOPool);
-void LLVertexBuffer::releaseBuffer()
-{
- if (mUsage == GL_STREAM_DRAW_ARB)
- {
- sStreamVBOPool.release(mGLBuffer, mMappedData, mSize);
- }
- else
- {
- sDynamicVBOPool.release(mGLBuffer, mMappedData, mSize);
- }
-
- mGLBuffer = 0;
- mMappedData = NULL;
+ if (sVBOPool)
+ {
+ llassert(mSize == 0);
+ llassert(mGLBuffer == 0);
+ llassert(mMappedData == nullptr);
- sGLCount--;
+ mSize = size;
+ sVBOPool->allocate(GL_ARRAY_BUFFER, mSize, mGLBuffer, mMappedData);
+ }
}
-void LLVertexBuffer::releaseIndices()
+void LLVertexBuffer::genIndices(U32 size)
{
- if (mUsage == GL_STREAM_DRAW_ARB)
- {
- sStreamIBOPool.release(mGLIndices, mMappedIndexData, mIndicesSize);
- }
- else
- {
- sDynamicIBOPool.release(mGLIndices, mMappedIndexData, mIndicesSize);
- }
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
+ llassert(sVBOPool);
- mGLIndices = 0;
- mMappedIndexData = NULL;
-
- sGLCount--;
+ if (sVBOPool)
+ {
+ llassert(mIndicesSize == 0);
+ llassert(mGLIndices == 0);
+ llassert(mMappedIndexData == nullptr);
+ mIndicesSize = size;
+ sVBOPool->allocate(GL_ELEMENT_ARRAY_BUFFER, mIndicesSize, mGLIndices, mMappedIndexData);
+ }
}
bool LLVertexBuffer::createGLBuffer(U32 size)
@@ -1067,22 +926,8 @@ bool LLVertexBuffer::createGLBuffer(U32 size)
bool success = true;
- mEmpty = true;
-
- mMappedDataUsingVBOs = useVBOs();
+ genBuffer(size);
- if (mMappedDataUsingVBOs)
- {
- genBuffer(size);
- }
- else
- {
- static int gl_buffer_idx = 0;
- mGLBuffer = ++gl_buffer_idx;
- mMappedData = (U8*)ll_aligned_malloc_16(size);
- mSize = size;
- }
-
if (!mMappedData)
{
success = false;
@@ -1104,27 +949,8 @@ bool LLVertexBuffer::createGLIndices(U32 size)
bool success = true;
- mEmpty = true;
-
- //pad by 16 bytes for aligned copies
- size += 16;
-
- mMappedIndexDataUsingVBOs = useVBOs();
-
- if (mMappedIndexDataUsingVBOs)
- {
- //pad by another 16 bytes for VBO pointer adjustment
- size += 16;
- genIndices(size);
- }
- else
- {
- mMappedIndexData = (U8*)ll_aligned_malloc_16(size);
- static int gl_buffer_idx = 0;
- mGLIndices = ++gl_buffer_idx;
- mIndicesSize = size;
- }
-
+ genIndices(size);
+
if (!mMappedIndexData)
{
success = false;
@@ -1136,43 +962,37 @@ void LLVertexBuffer::destroyGLBuffer()
{
if (mGLBuffer || mMappedData)
{
- if (mMappedDataUsingVBOs)
- {
- releaseBuffer();
- }
- else
- {
- ll_aligned_free_16((void*)mMappedData);
- mMappedData = NULL;
- mEmpty = true;
- }
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
+ //llassert(sVBOPool);
+ if (sVBOPool)
+ {
+ sVBOPool->free(GL_ARRAY_BUFFER, mSize, mGLBuffer, mMappedData);
+ }
+
+ mSize = 0;
+ mGLBuffer = 0;
+ mMappedData = nullptr;
}
-
- mGLBuffer = 0;
- //unbind();
}
void LLVertexBuffer::destroyGLIndices()
{
if (mGLIndices || mMappedIndexData)
{
- if (mMappedIndexDataUsingVBOs)
- {
- releaseIndices();
- }
- else
- {
- ll_aligned_free_16((void*)mMappedIndexData);
- mMappedIndexData = NULL;
- mEmpty = true;
- }
- }
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
+ //llassert(sVBOPool);
+ if (sVBOPool)
+ {
+ sVBOPool->free(GL_ELEMENT_ARRAY_BUFFER, mIndicesSize, mGLIndices, mMappedIndexData);
+ }
- mGLIndices = 0;
- //unbind();
+ mIndicesSize = 0;
+ mGLIndices = 0;
+ mMappedIndexData = nullptr;
+ }
}
-bool LLVertexBuffer::updateNumVerts(S32 nverts)
+bool LLVertexBuffer::updateNumVerts(U32 nverts)
{
llassert(nverts >= 0);
@@ -1186,19 +1006,17 @@ bool LLVertexBuffer::updateNumVerts(S32 nverts)
U32 needed_size = calcOffsets(mTypeMask, mOffsets, nverts);
- if (needed_size > mSize || needed_size <= mSize/2)
- {
- success &= createGLBuffer(needed_size);
- }
+ if (needed_size != mSize)
+ {
+ success &= createGLBuffer(needed_size);
+ }
- sVertexCount -= mNumVerts;
+ llassert(mSize == needed_size);
mNumVerts = nverts;
- sVertexCount += mNumVerts;
-
return success;
}
-bool LLVertexBuffer::updateNumIndices(S32 nindices)
+bool LLVertexBuffer::updateNumIndices(U32 nindices)
{
llassert(nindices >= 0);
@@ -1206,22 +1024,18 @@ bool LLVertexBuffer::updateNumIndices(S32 nindices)
U32 needed_size = sizeof(U16) * nindices;
- if (needed_size > mIndicesSize || needed_size <= mIndicesSize/2)
+ if (needed_size != mIndicesSize)
{
success &= createGLIndices(needed_size);
}
- sIndexCount -= mNumIndices;
+ llassert(mIndicesSize == needed_size);
mNumIndices = nindices;
- sIndexCount += mNumIndices;
-
return success;
}
-bool LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
+bool LLVertexBuffer::allocateBuffer(U32 nverts, U32 nindices)
{
- stop_glerror();
-
if (nverts < 0 || nindices < 0 ||
nverts > 65536)
{
@@ -1233,735 +1047,215 @@ bool LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
success &= updateNumVerts(nverts);
success &= updateNumIndices(nindices);
- if (create && (nverts || nindices))
- {
- //actually allocate space for the vertex buffer if using VBO mapping
- flush(); //unmap
-
- if (gGLManager.mHasVertexArrayObject && useVBOs() && sUseVAO)
- {
-#if GL_ARB_vertex_array_object
- mGLArray = getVAOName();
-#endif
- setupVertexArray();
- }
- }
-
return success;
}
-void LLVertexBuffer::setupVertexArray()
-{
- if (!mGLArray)
- {
- return;
- }
-
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
-#if GL_ARB_vertex_array_object
- glBindVertexArray(mGLArray);
-#endif
- sGLRenderArray = mGLArray;
-
- static const U32 attrib_size[] =
- {
- 3, //TYPE_VERTEX,
- 3, //TYPE_NORMAL,
- 2, //TYPE_TEXCOORD0,
- 2, //TYPE_TEXCOORD1,
- 2, //TYPE_TEXCOORD2,
- 2, //TYPE_TEXCOORD3,
- 4, //TYPE_COLOR,
- 4, //TYPE_EMISSIVE,
- 4, //TYPE_TANGENT,
- 1, //TYPE_WEIGHT,
- 4, //TYPE_WEIGHT4,
- 4, //TYPE_CLOTHWEIGHT,
- 1, //TYPE_TEXTURE_INDEX
- };
-
- static const U32 attrib_type[] =
- {
- GL_FLOAT, //TYPE_VERTEX,
- GL_FLOAT, //TYPE_NORMAL,
- GL_FLOAT, //TYPE_TEXCOORD0,
- GL_FLOAT, //TYPE_TEXCOORD1,
- GL_FLOAT, //TYPE_TEXCOORD2,
- GL_FLOAT, //TYPE_TEXCOORD3,
- GL_UNSIGNED_BYTE, //TYPE_COLOR,
- GL_UNSIGNED_BYTE, //TYPE_EMISSIVE,
- GL_FLOAT, //TYPE_TANGENT,
- GL_FLOAT, //TYPE_WEIGHT,
- GL_FLOAT, //TYPE_WEIGHT4,
- GL_FLOAT, //TYPE_CLOTHWEIGHT,
- GL_UNSIGNED_INT, //TYPE_TEXTURE_INDEX
- };
-
- static const bool attrib_integer[] =
- {
- false, //TYPE_VERTEX,
- false, //TYPE_NORMAL,
- false, //TYPE_TEXCOORD0,
- false, //TYPE_TEXCOORD1,
- false, //TYPE_TEXCOORD2,
- false, //TYPE_TEXCOORD3,
- false, //TYPE_COLOR,
- false, //TYPE_EMISSIVE,
- false, //TYPE_TANGENT,
- false, //TYPE_WEIGHT,
- false, //TYPE_WEIGHT4,
- false, //TYPE_CLOTHWEIGHT,
- true, //TYPE_TEXTURE_INDEX
- };
-
- static const U32 attrib_normalized[] =
- {
- GL_FALSE, //TYPE_VERTEX,
- GL_FALSE, //TYPE_NORMAL,
- GL_FALSE, //TYPE_TEXCOORD0,
- GL_FALSE, //TYPE_TEXCOORD1,
- GL_FALSE, //TYPE_TEXCOORD2,
- GL_FALSE, //TYPE_TEXCOORD3,
- GL_TRUE, //TYPE_COLOR,
- GL_TRUE, //TYPE_EMISSIVE,
- GL_FALSE, //TYPE_TANGENT,
- GL_FALSE, //TYPE_WEIGHT,
- GL_FALSE, //TYPE_WEIGHT4,
- GL_FALSE, //TYPE_CLOTHWEIGHT,
- GL_FALSE, //TYPE_TEXTURE_INDEX
- };
-
- bindGLBuffer(true);
- bindGLIndices(true);
-
- for (U32 i = 0; i < TYPE_MAX; ++i)
- {
- if (mTypeMask & (1 << i))
- {
- glEnableVertexAttribArrayARB(i);
-
- if (attrib_integer[i])
- {
-#if !LL_DARWIN
- //glVertexattribIPointer requires GLSL 1.30 or later
- if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30)
- {
- // nat 2018-10-24: VS 2017 also notices the issue
- // described below, and warns even with reinterpret_cast.
- // Cast via intptr_t to make it painfully obvious to the
- // compiler that we're doing this intentionally.
- glVertexAttribIPointer(i, attrib_size[i], attrib_type[i], sTypeSize[i],
- reinterpret_cast<const GLvoid*>(intptr_t(mOffsets[i])));
- }
-#endif
- }
- else
- {
- // nat 2016-12-16: With 64-bit clang compile, the compiler
- // produces an error if we simply cast mOffsets[i] -- an S32
- // -- to (GLvoid *), the type of the parameter. It correctly
- // points out that there's no way an S32 could fit a real
- // pointer value. Ruslan asserts that in this case the last
- // param is interpreted as an array data offset within the VBO
- // rather than as an actual pointer, so it's okay.
- glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i],
- attrib_normalized[i], sTypeSize[i],
- reinterpret_cast<GLvoid*>(intptr_t(mOffsets[i])));
- }
- }
- else
- {
- glDisableVertexAttribArrayARB(i);
- }
- }
-
- //draw a dummy triangle to set index array pointer
- //glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, NULL);
-
- unbind();
-}
-
-bool LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
-{
- llassert(newnverts >= 0);
- llassert(newnindices >= 0);
-
- bool success = true;
-
- success &= updateNumVerts(newnverts);
- success &= updateNumIndices(newnindices);
-
- if (useVBOs())
- {
- flush(); //unmap
-
- if (mGLArray)
- { //if size changed, offsets changed
- setupVertexArray();
- }
- }
-
- return success;
-}
-
-bool LLVertexBuffer::useVBOs() const
-{
- //it's generally ineffective to use VBO for things that are streaming on apple
- return (mUsage != 0);
-}
-
//----------------------------------------------------------------------------
-bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count)
+// if no gap between region and given range exists, expand region to cover given range and return true
+// otherwise return false
+bool expand_region(LLVertexBuffer::MappedRegion& region, U32 start, U32 end)
{
- S32 end = index+count;
- S32 region_end = region.mIndex+region.mCount;
- if (end < region.mIndex ||
- index > region_end)
+ if (end < region.mStart ||
+ start > region.mEnd)
{ //gap exists, do not merge
return false;
}
- S32 new_end = llmax(end, region_end);
- S32 new_index = llmin(index, region.mIndex);
- region.mIndex = new_index;
- region.mCount = new_end-new_index;
+ region.mStart = llmin(region.mStart, start);
+ region.mEnd = llmax(region.mEnd, end);
+
return true;
}
// Map for data access
-U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range)
+U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 index, S32 count)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
- bindGLBuffer(true);
- if (mFinal)
- {
- LL_ERRS() << "LLVertexBuffer::mapVeretxBuffer() called on a finalized buffer." << LL_ENDL;
- }
- if (!useVBOs() && !mMappedData && !mMappedIndexData)
- {
- LL_ERRS() << "LLVertexBuffer::mapVertexBuffer() called on unallocated buffer." << LL_ENDL;
- }
-
- if (useVBOs())
- {
- if (!mMappable || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
- {
- if (count == -1)
- {
- count = mNumVerts-index;
- }
-
- bool mapped = false;
- //see if range is already mapped
- for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
- {
- MappedRegion& region = mMappedVertexRegions[i];
- if (region.mType == type)
- {
- if (expand_region(region, index, count))
- {
- mapped = true;
- break;
- }
- }
- }
-
- if (!mapped)
- {
- //not already mapped, map new region
- MappedRegion region(type, mMappable && map_range ? -1 : index, count);
- mMappedVertexRegions.push_back(region);
- }
- }
-
- if (mVertexLocked && map_range)
- {
- LL_ERRS() << "Attempted to map a specific range of a buffer that was already mapped." << LL_ENDL;
- }
-
- if (!mVertexLocked)
- {
- mVertexLocked = true;
- sMappedCount++;
- stop_glerror();
-
- if(!mMappable)
- {
- map_range = false;
- }
- else
- {
- U8* src = NULL;
- waitFence();
- if (gGLManager.mHasMapBufferRange)
- {
- if (map_range)
- {
-#ifdef GL_ARB_map_buffer_range
- S32 offset = mOffsets[type] + sTypeSize[type]*index;
- S32 length = (sTypeSize[type]*count+0xF) & ~0xF;
- src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length,
- GL_MAP_WRITE_BIT |
- GL_MAP_FLUSH_EXPLICIT_BIT |
- GL_MAP_INVALIDATE_RANGE_BIT);
-#endif
- }
- else
- {
-#ifdef GL_ARB_map_buffer_range
-
- if (gDebugGL)
- {
- GLint size = 0;
- glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size);
-
- if (size < mSize)
- {
- LL_ERRS() << "Invalid buffer size." << LL_ENDL;
- }
- }
-
- src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize,
- GL_MAP_WRITE_BIT |
- GL_MAP_FLUSH_EXPLICIT_BIT);
-#endif
- }
- }
- else if (gGLManager.mHasFlushBufferRange)
- {
- if (map_range)
- {
-#ifndef LL_MESA_HEADLESS
- glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE);
- glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE);
-#endif
- src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- }
- else
- {
- src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- }
- }
- else
- {
- map_range = false;
- src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- }
-
- llassert(src != NULL);
+
+ if (count == -1)
+ {
+ count = mNumVerts - index;
+ }
- mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src);
- mAlignedOffset = mMappedData - src;
-
- stop_glerror();
- }
-
- if (!mMappedData)
- {
- log_glerror();
+ U32 start = mOffsets[type] + sTypeSize[type] * index;
+ U32 end = start + sTypeSize[type] * count-1;
- //check the availability of memory
- LLMemory::logMemoryInfo(true);
-
- if(mMappable)
- {
- //--------------------
- //print out more debug info before crash
- LL_INFOS() << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << LL_ENDL;
- GLint size;
- glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size);
- LL_INFOS() << "GL_ARRAY_BUFFER_ARB size is " << size << LL_ENDL;
- //--------------------
-
- GLint buff;
- glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
- if ((GLuint)buff != mGLBuffer)
- {
- LL_ERRS() << "Invalid GL vertex buffer bound: " << buff << LL_ENDL;
- }
-
-
- LL_ERRS() << "glMapBuffer returned NULL (no vertex data)" << LL_ENDL;
- }
- else
- {
- LL_ERRS() << "memory allocation for vertex data failed." << LL_ENDL;
- }
- }
- }
- }
- else
+ bool flagged = false;
+ // flag region as mapped
+ for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
{
- map_range = false;
- }
-
- if (map_range && gGLManager.mHasMapBufferRange && mMappable)
- {
- return mMappedData;
+ MappedRegion& region = mMappedVertexRegions[i];
+ if (expand_region(region, start, end))
+ {
+ flagged = true;
+ break;
+ }
}
- else
+
+ if (!flagged)
{
- return mMappedData+mOffsets[type]+sTypeSize[type]*index;
+ //didn't expand an existing region, make a new one
+ mMappedVertexRegions.push_back({ start, end });
}
+
+ return mMappedData+mOffsets[type]+sTypeSize[type]*index;
}
-U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
+U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
- bindGLIndices(true);
- if (mFinal)
- {
- LL_ERRS() << "LLVertexBuffer::mapIndexBuffer() called on a finalized buffer." << LL_ENDL;
- }
- if (!useVBOs() && !mMappedData && !mMappedIndexData)
+
+ if (count == -1)
{
- LL_ERRS() << "LLVertexBuffer::mapIndexBuffer() called on unallocated buffer." << LL_ENDL;
+ count = mNumIndices-index;
}
- if (useVBOs())
- {
- if (!mMappable || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
- {
- if (count == -1)
- {
- count = mNumIndices-index;
- }
-
- bool mapped = false;
- //see if range is already mapped
- for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
- {
- MappedRegion& region = mMappedIndexRegions[i];
- if (expand_region(region, index, count))
- {
- mapped = true;
- break;
- }
- }
-
- if (!mapped)
- {
- //not already mapped, map new region
- MappedRegion region(TYPE_INDEX, mMappable && map_range ? -1 : index, count);
- mMappedIndexRegions.push_back(region);
- }
- }
-
- if (mIndexLocked && map_range)
- {
- LL_ERRS() << "Attempted to map a specific range of a buffer that was already mapped." << LL_ENDL;
- }
-
- if (!mIndexLocked)
- {
- mIndexLocked = true;
- sMappedCount++;
- stop_glerror();
-
- if (gDebugGL && useVBOs())
- {
- GLint elem = 0;
- glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &elem);
-
- if (elem != mGLIndices)
- {
- LL_ERRS() << "Wrong index buffer bound!" << LL_ENDL;
- }
- }
-
- if(!mMappable)
- {
- map_range = false;
- }
- else
- {
- U8* src = NULL;
- waitFence();
- if (gGLManager.mHasMapBufferRange)
- {
- if (map_range)
- {
-#ifdef GL_ARB_map_buffer_range
- S32 offset = sizeof(U16)*index;
- S32 length = sizeof(U16)*count;
- src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length,
- GL_MAP_WRITE_BIT |
- GL_MAP_FLUSH_EXPLICIT_BIT |
- GL_MAP_INVALIDATE_RANGE_BIT);
-#endif
- }
- else
- {
-#ifdef GL_ARB_map_buffer_range
- src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices,
- GL_MAP_WRITE_BIT |
- GL_MAP_FLUSH_EXPLICIT_BIT);
-#endif
- }
- }
- else if (gGLManager.mHasFlushBufferRange)
- {
- if (map_range)
- {
-#ifndef LL_MESA_HEADLESS
- glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE);
- glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE);
-#endif
- src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- }
- else
- {
- src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- }
- }
- else
- {
- map_range = false;
- src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- }
-
- llassert(src != NULL);
+ U32 start = sizeof(U16) * index;
+ U32 end = start + sizeof(U16) * count-1;
+ bool flagged = false;
+ // flag region as mapped
+ for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
+ {
+ MappedRegion& region = mMappedIndexRegions[i];
+ if (expand_region(region, start, end))
+ {
+ flagged = true;
+ break;
+ }
+ }
- mMappedIndexData = src; //LL_NEXT_ALIGNED_ADDRESS<U8>(src);
- mAlignedIndexOffset = mMappedIndexData - src;
- stop_glerror();
- }
- }
+ if (!flagged)
+ {
+ //didn't expand an existing region, make a new one
+ mMappedIndexRegions.push_back({ start, end });
+ }
- if (!mMappedIndexData)
- {
- log_glerror();
- LLMemory::logMemoryInfo(true);
+ return mMappedIndexData + sizeof(U16)*index;
+}
- if(mMappable)
- {
- GLint buff;
- glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
- if ((GLuint)buff != mGLIndices)
- {
- LL_ERRS() << "Invalid GL index buffer bound: " << buff << LL_ENDL;
- }
+// flush the given byte range
+// target -- "targret" 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)
+{
+ if (end != 0)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("glBufferSubData");
+ LL_PROFILE_ZONE_NUM(start);
+ LL_PROFILE_ZONE_NUM(end);
+ LL_PROFILE_ZONE_NUM(end-start);
- LL_ERRS() << "glMapBuffer returned NULL (no index data)" << LL_ENDL;
- }
- else
- {
- LL_ERRS() << "memory allocation for Index data failed. " << LL_ENDL;
- }
- }
- }
- else
- {
- map_range = false;
- }
+ constexpr U32 block_size = 8192;
- if (map_range && gGLManager.mHasMapBufferRange && mMappable)
- {
- return mMappedIndexData;
- }
- else
- {
- return mMappedIndexData + sizeof(U16)*index;
- }
+ for (U32 i = start; i <= end; i += block_size)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("glBufferSubData block");
+ //LL_PROFILE_GPU_ZONE("glBufferSubData");
+ U32 tend = llmin(i + block_size, end);
+ U32 size = tend - i + 1;
+ glBufferSubData(target, i, size, (U8*) data + (i-start));
+ }
+ }
}
void LLVertexBuffer::unmapBuffer()
{
- if (!useVBOs())
- {
- return; //nothing to unmap
- }
+ struct SortMappedRegion
+ {
+ bool operator()(const MappedRegion& lhs, const MappedRegion& rhs)
+ {
+ return lhs.mStart < rhs.mStart;
+ }
+ };
- bool updated_all = false;
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
- if (mMappedData && mVertexLocked)
+ if (!mMappedVertexRegions.empty())
{
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - vertex");
- bindGLBuffer(true);
- updated_all = mIndexLocked; //both vertex and index buffers done updating
+ if (sGLRenderBuffer != mGLBuffer)
+ {
+ glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer);
+ sGLRenderBuffer = mGLBuffer;
+ }
+
+ U32 start = 0;
+ U32 end = 0;
- if(!mMappable)
- {
- if (!mMappedVertexRegions.empty())
- {
- stop_glerror();
- for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
- {
- const MappedRegion& region = mMappedVertexRegions[i];
- S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
- S32 length = sTypeSize[region.mType]*region.mCount;
- if (mSize >= length + offset)
- {
- glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, (U8*)mMappedData + offset);
- }
- else
- {
- GLint size = 0;
- glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size);
- LL_WARNS() << "Attempted to map regions to a buffer that is too small, "
- << "mapped size: " << mSize
- << ", gl buffer size: " << size
- << ", length: " << length
- << ", offset: " << offset
- << LL_ENDL;
- }
- stop_glerror();
- }
+ std::sort(mMappedVertexRegions.begin(), mMappedVertexRegions.end(), SortMappedRegion());
- mMappedVertexRegions.clear();
- }
- else
- {
- stop_glerror();
- glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), (U8*) mMappedData);
- stop_glerror();
- }
- }
- else
+ for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
{
- if (gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
- {
- if (!mMappedVertexRegions.empty())
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - flush vertex");
- for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
- {
- const MappedRegion& region = mMappedVertexRegions[i];
- S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
- S32 length = sTypeSize[region.mType]*region.mCount;
- if (gGLManager.mHasMapBufferRange)
- {
-#ifdef GL_ARB_map_buffer_range
- glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length);
-#endif
- }
- else if (gGLManager.mHasFlushBufferRange)
- {
-#ifndef LL_MESA_HEADLESS
- glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER_ARB, offset, length);
-#endif
- }
- }
-
- mMappedVertexRegions.clear();
- }
- }
- stop_glerror();
- glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
- stop_glerror();
-
- mMappedData = NULL;
+ const MappedRegion& region = mMappedVertexRegions[i];
+ if (region.mStart == end + 1)
+ {
+ end = region.mEnd;
+ }
+ else
+ {
+ flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start);
+ start = region.mStart;
+ end = region.mEnd;
+ }
}
- mVertexLocked = false;
- sMappedCount--;
+ flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start);
+
+ mMappedVertexRegions.clear();
}
- if (mMappedIndexData && mIndexLocked)
+ if (!mMappedIndexRegions.empty())
{
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - index");
- bindGLIndices();
- if(!mMappable)
- {
- if (!mMappedIndexRegions.empty())
- {
- for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
- {
- const MappedRegion& region = mMappedIndexRegions[i];
- S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
- S32 length = sizeof(U16)*region.mCount;
- if (mIndicesSize >= length + offset)
- {
- glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, (U8*) mMappedIndexData+offset);
- }
- else
- {
- GLint size = 0;
- glGetBufferParameterivARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size);
- LL_WARNS() << "Attempted to map regions to a buffer that is too small, "
- << "mapped size: " << mIndicesSize
- << ", gl buffer size: " << size
- << ", length: " << length
- << ", offset: " << offset
- << LL_ENDL;
- }
- stop_glerror();
- }
- mMappedIndexRegions.clear();
- }
- else
- {
- stop_glerror();
- glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), (U8*) mMappedIndexData);
- stop_glerror();
- }
- }
- else
- {
- if (gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
- {
- if (!mMappedIndexRegions.empty())
- {
- for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - flush index");
- const MappedRegion& region = mMappedIndexRegions[i];
- S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
- S32 length = sizeof(U16)*region.mCount;
- if (gGLManager.mHasMapBufferRange)
- {
-#ifdef GL_ARB_map_buffer_range
- glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
-#endif
- }
- else if (gGLManager.mHasFlushBufferRange)
- {
-#ifdef GL_APPLE_flush_buffer_range
-#ifndef LL_MESA_HEADLESS
- glFlushMappedBufferRangeAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
-#endif
-#endif
- }
- stop_glerror();
- }
+ if (mGLIndices != sGLRenderIndices)
+ {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices);
+ sGLRenderIndices = mGLIndices;
+ }
+ U32 start = 0;
+ U32 end = 0;
- mMappedIndexRegions.clear();
- }
- }
-
- glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
+ std::sort(mMappedIndexRegions.begin(), mMappedIndexRegions.end(), SortMappedRegion());
- mMappedIndexData = NULL;
- }
+ for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
+ {
+ const MappedRegion& region = mMappedIndexRegions[i];
+ if (region.mStart == end + 1)
+ {
+ end = region.mEnd;
+ }
+ else
+ {
+ flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start);
+ start = region.mStart;
+ end = region.mEnd;
+ }
+ }
- mIndexLocked = false;
- sMappedCount--;
- }
+ flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start);
- if(updated_all)
- {
- mEmpty = false;
+ mMappedIndexRegions.clear();
}
}
//----------------------------------------------------------------------------
-template <class T,S32 type> struct VertexBufferStrider
+template <class T,LLVertexBuffer::AttributeType type> struct VertexBufferStrider
{
typedef LLStrider<T> strider_t;
static bool get(LLVertexBuffer& vbo,
strider_t& strider,
- S32 index, S32 count, bool map_range)
+ S32 index, S32 count)
{
if (type == LLVertexBuffer::TYPE_INDEX)
{
- U8* ptr = vbo.mapIndexBuffer(index, count, map_range);
+ U8* ptr = vbo.mapIndexBuffer(index, count);
if (ptr == NULL)
{
@@ -1975,9 +1269,9 @@ template <class T,S32 type> struct VertexBufferStrider
}
else if (vbo.hasDataType(type))
{
- S32 stride = LLVertexBuffer::sTypeSize[type];
+ U32 stride = LLVertexBuffer::sTypeSize[type];
- U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range);
+ U8* ptr = vbo.mapVertexBuffer(type, index, count);
if (ptr == NULL)
{
@@ -1997,590 +1291,216 @@ template <class T,S32 type> struct VertexBufferStrider
}
};
-bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector4a>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector4a>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector4a,TYPE_VERTEX>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector4a,TYPE_VERTEX>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getTangentStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getTangentStrider(LLStrider<LLVector3>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector3,TYPE_TANGENT>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector3,TYPE_TANGENT>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getTangentStrider(LLStrider<LLVector4a>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getTangentStrider(LLStrider<LLVector4a>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector4a,TYPE_TANGENT>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector4a,TYPE_TANGENT>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getEmissiveStrider(LLStrider<LLColor4U>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getEmissiveStrider(LLStrider<LLColor4U>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLColor4U,TYPE_EMISSIVE>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLColor4U,TYPE_EMISSIVE>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index, count);
}
//----------------------------------------------------------------------------
-bool LLVertexBuffer::bindGLArray()
-{
- if (mGLArray && sGLRenderArray != mGLArray)
- {
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
-#if GL_ARB_vertex_array_object
- glBindVertexArray(mGLArray);
-#endif
- sGLRenderArray = mGLArray;
- }
- //really shouldn't be necessary, but some drivers don't properly restore the
- //state of GL_ELEMENT_ARRAY_BUFFER_BINDING
- bindGLIndices();
-
- return true;
- }
-
- return false;
-}
-
-bool LLVertexBuffer::bindGLBuffer(bool force_bind)
+// Set for rendering
+void LLVertexBuffer::setBuffer()
{
- bindGLArray();
+ // no data may be pending
+ llassert(mMappedVertexRegions.empty());
+ llassert(mMappedIndexRegions.empty());
- bool ret = false;
+ // a shader must be bound
+ llassert(LLGLSLShader::sCurBoundShaderPtr);
- if (useVBOs() && (force_bind || (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive))))
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
- sGLRenderBuffer = mGLBuffer;
- sBindCount++;
- sVBOActive = true;
-
- llassert(!mGLArray || sGLRenderArray == mGLArray);
-
- ret = true;
- }
+ U32 data_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask;
- return ret;
-}
+ // this Vertex Buffer must provide all necessary attributes for currently bound shader
+ llassert_msg((data_mask & mTypeMask) == data_mask,
+ "Attribute mask mismatch! mTypeMask should be a superset of data_mask. data_mask: 0x"
+ << std::hex << data_mask << " mTypeMask: 0x" << mTypeMask << " Missing: 0x" << (data_mask & ~mTypeMask) << std::dec);
-bool LLVertexBuffer::bindGLBufferFast()
-{
- if (mGLBuffer != sGLRenderBuffer || !sVBOActive)
+ if (sGLRenderBuffer != mGLBuffer)
{
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer);
sGLRenderBuffer = mGLBuffer;
- sBindCount++;
- sVBOActive = true;
-
- return true;
- }
-
- return false;
-}
-bool LLVertexBuffer::bindGLIndices(bool force_bind)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
- bindGLArray();
-
- bool ret = false;
- if (useVBOs() && (force_bind || (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive))))
- {
- /*if (sMapped)
- {
- LL_ERRS() << "VBO bound while another VBO mapped!" << LL_ENDL;
- }*/
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices);
- sGLRenderIndices = mGLIndices;
- stop_glerror();
- sBindCount++;
- sIBOActive = true;
- ret = true;
- }
-
- return ret;
-}
-
-bool LLVertexBuffer::bindGLIndicesFast()
-{
- if (mGLIndices != sGLRenderIndices || !sIBOActive)
- {
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices);
- sGLRenderIndices = mGLIndices;
- sBindCount++;
- sIBOActive = true;
-
- return true;
+ setupVertexBuffer();
}
-
- return false;
-}
-
-void LLVertexBuffer::flush()
-{
- if (useVBOs())
- {
- unmapBuffer();
- }
-}
-
-// bind for transform feedback (quick 'n dirty)
-void LLVertexBuffer::bindForFeedback(U32 channel, U32 type, U32 index, U32 count)
-{
-#ifdef GL_TRANSFORM_FEEDBACK_BUFFER
- U32 offset = mOffsets[type] + sTypeSize[type]*index;
- U32 size= (sTypeSize[type]*count);
- glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, channel, mGLBuffer, offset, size);
-#endif
-}
-
-// Set for rendering
-void LLVertexBuffer::setBuffer(U32 data_mask)
-{
- flush();
-
- //set up pointers if the data mask is different ...
- bool setup = (sLastMask != data_mask);
-
- if (gDebugGL && data_mask != 0)
- { //make sure data requirements are fulfilled
- LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
- if (shader)
- {
- U32 required_mask = 0;
- for (U32 i = 0; i < LLVertexBuffer::TYPE_TEXTURE_INDEX; ++i)
- {
- if (shader->getAttribLocation(i) > -1)
- {
- U32 required = 1 << i;
- if ((data_mask & required) == 0)
- {
- LL_WARNS() << "Missing attribute: " << LLShaderMgr::instance()->mReservedAttribs[i] << LL_ENDL;
- }
-
- required_mask |= required;
- }
- }
-
- if ((data_mask & required_mask) != required_mask)
- {
-
- U32 unsatisfied_mask = (required_mask & ~data_mask);
-
- for (U32 i = 0; i < TYPE_MAX; i++)
- {
- U32 unsatisfied_flag = unsatisfied_mask & (1 << i);
- switch (unsatisfied_flag)
- {
- case 0: break;
- case MAP_VERTEX: LL_INFOS() << "Missing vert pos" << LL_ENDL; break;
- case MAP_NORMAL: LL_INFOS() << "Missing normals" << LL_ENDL; break;
- case MAP_TEXCOORD0: LL_INFOS() << "Missing TC 0" << LL_ENDL; break;
- case MAP_TEXCOORD1: LL_INFOS() << "Missing TC 1" << LL_ENDL; break;
- case MAP_TEXCOORD2: LL_INFOS() << "Missing TC 2" << LL_ENDL; break;
- case MAP_TEXCOORD3: LL_INFOS() << "Missing TC 3" << LL_ENDL; break;
- case MAP_COLOR: LL_INFOS() << "Missing vert color" << LL_ENDL; break;
- case MAP_EMISSIVE: LL_INFOS() << "Missing emissive" << LL_ENDL; break;
- case MAP_TANGENT: LL_INFOS() << "Missing tangent" << LL_ENDL; break;
- case MAP_WEIGHT: LL_INFOS() << "Missing weight" << LL_ENDL; break;
- case MAP_WEIGHT4: LL_INFOS() << "Missing weightx4" << LL_ENDL; break;
- case MAP_CLOTHWEIGHT: LL_INFOS() << "Missing clothweight" << LL_ENDL; break;
- case MAP_TEXTURE_INDEX: LL_INFOS() << "Missing tex index" << LL_ENDL; break;
- default: LL_INFOS() << "Missing who effin knows: " << unsatisfied_flag << LL_ENDL;
- }
- }
-
- // TYPE_INDEX is beyond TYPE_MAX, so check for it individually
- if (unsatisfied_mask & (1 << TYPE_INDEX))
- {
- LL_INFOS() << "Missing indices" << LL_ENDL;
- }
-
- LL_ERRS() << "Shader consumption mismatches data provision." << LL_ENDL;
- }
- }
- }
-
- if (useVBOs())
- {
- if (mGLArray)
- {
- bindGLArray();
- setup = false; //do NOT perform pointer setup if using VAO
- }
- else
- {
- const bool bindBuffer = bindGLBuffer();
- const bool bindIndices = bindGLIndices();
-
- setup = setup || bindBuffer || bindIndices;
- }
-
- if (gDebugGL && !mGLArray)
- {
- GLint buff;
- glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
- if ((GLuint)buff != mGLBuffer)
- {
- if (gDebugSession)
- {
- gFailLog << "Invalid GL vertex buffer bound: " << buff << std::endl;
- }
- else
- {
- LL_ERRS() << "Invalid GL vertex buffer bound: " << buff << LL_ENDL;
- }
- }
-
- if (mGLIndices)
- {
- glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
- if ((GLuint)buff != mGLIndices)
- {
- if (gDebugSession)
- {
- gFailLog << "Invalid GL index buffer bound: " << buff << std::endl;
- }
- else
- {
- LL_ERRS() << "Invalid GL index buffer bound: " << buff << LL_ENDL;
- }
- }
- }
- }
-
-
- }
- else
- {
- if (sGLRenderArray)
- {
-#if GL_ARB_vertex_array_object
- glBindVertexArray(0);
-#endif
- sGLRenderArray = 0;
- sGLRenderIndices = 0;
- sIBOActive = false;
- }
-
- if (mGLBuffer)
- {
- if (sVBOActive)
- {
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- sBindCount++;
- sVBOActive = false;
- setup = true; // ... or a VBO is deactivated
- }
- if (sGLRenderBuffer != mGLBuffer)
- {
- sGLRenderBuffer = mGLBuffer;
- setup = true; // ... or a client memory pointer changed
- }
- }
- if (mGLIndices)
- {
- if (sIBOActive)
- {
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
- sBindCount++;
- sIBOActive = false;
- }
-
- sGLRenderIndices = mGLIndices;
- }
- }
-
- if (!mGLArray)
- {
- setupClientArrays(data_mask);
- }
-
- if (mGLBuffer)
- {
- if (data_mask && setup)
- {
- setupVertexBuffer(data_mask); // subclass specific setup (virtual function)
- sSetCount++;
- }
- }
-}
-
-void LLVertexBuffer::setBufferFast(U32 data_mask)
-{
- if (useVBOs())
+ else if (sLastMask != data_mask)
{
- //set up pointers if the data mask is different ...
- bool setup = (sLastMask != data_mask);
-
- const bool bindBuffer = bindGLBufferFast();
- const bool bindIndices = bindGLIndicesFast();
-
- setup = setup || bindBuffer || bindIndices;
-
- setupClientArrays(data_mask);
-
- if (data_mask && setup)
- {
- setupVertexBufferFast(data_mask);
- sSetCount++;
- }
+ setupVertexBuffer();
+ sLastMask = data_mask;
}
- else
+
+ if (mGLIndices != sGLRenderIndices)
{
- //fallback to slow path when not using VBOs
- setBuffer(data_mask);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices);
+ sGLRenderIndices = mGLIndices;
}
}
// virtual (default)
-void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
+void LLVertexBuffer::setupVertexBuffer()
{
- stop_glerror();
- U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData;
+ U8* base = nullptr;
- if (gDebugGL && ((data_mask & mTypeMask) != data_mask))
- {
- for (U32 i = 0; i < LLVertexBuffer::TYPE_MAX; ++i)
- {
- U32 mask = 1 << i;
- if (mask & data_mask && !(mask & mTypeMask))
- { //bit set in data_mask, but not set in mTypeMask
- LL_WARNS() << "Missing required component " << vb_type_name[i] << LL_ENDL;
- }
- }
- LL_ERRS() << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << LL_ENDL;
- }
-
- if (data_mask & MAP_NORMAL)
- {
- S32 loc = TYPE_NORMAL;
- void* ptr = (void*)(base + mOffsets[TYPE_NORMAL]);
- glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr);
- }
- if (data_mask & MAP_TEXCOORD3)
- {
- S32 loc = TYPE_TEXCOORD3;
- void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]);
- glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr);
- }
- if (data_mask & MAP_TEXCOORD2)
- {
- S32 loc = TYPE_TEXCOORD2;
- void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]);
- glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr);
- }
- if (data_mask & MAP_TEXCOORD1)
- {
- S32 loc = TYPE_TEXCOORD1;
- void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD1]);
- glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr);
- }
- if (data_mask & MAP_TANGENT)
- {
- S32 loc = TYPE_TANGENT;
- void* ptr = (void*)(base + mOffsets[TYPE_TANGENT]);
- glVertexAttribPointerARB(loc, 4,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr);
- }
- if (data_mask & MAP_TEXCOORD0)
- {
- S32 loc = TYPE_TEXCOORD0;
- void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]);
- glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr);
- }
- if (data_mask & MAP_COLOR)
- {
- S32 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]);
- glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr);
- }
- if (data_mask & MAP_EMISSIVE)
- {
- S32 loc = TYPE_EMISSIVE;
- void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]);
- glVertexAttribPointerARB(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;
- glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
- }
- }
- if (data_mask & MAP_WEIGHT)
- {
- S32 loc = TYPE_WEIGHT;
- void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]);
- glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr);
- }
- if (data_mask & MAP_WEIGHT4)
- {
- S32 loc = TYPE_WEIGHT4;
- void* ptr = (void*)(base+mOffsets[TYPE_WEIGHT4]);
- glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr);
- }
- if (data_mask & MAP_CLOTHWEIGHT)
- {
- S32 loc = TYPE_CLOTHWEIGHT;
- void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]);
- glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
- }
- if (data_mask & MAP_TEXTURE_INDEX &&
- (gGLManager.mGLSLVersionMajor >= 2 || gGLManager.mGLSLVersionMinor >= 30)) //indexed texture rendering requires GLSL 1.30 or later
- {
-#if !LL_DARWIN
- S32 loc = TYPE_TEXTURE_INDEX;
- void *ptr = (void*) (base + mOffsets[TYPE_VERTEX] + 12);
- glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
-#endif
- }
- if (data_mask & MAP_VERTEX)
- {
- S32 loc = TYPE_VERTEX;
- void* ptr = (void*)(base + mOffsets[TYPE_VERTEX]);
- glVertexAttribPointerARB(loc, 3,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
- }
-
- llglassertok();
-}
-
-void LLVertexBuffer::setupVertexBufferFast(U32 data_mask)
-{
- U8* base = (U8*)mAlignedOffset;
+ U32 data_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask;
if (data_mask & MAP_NORMAL)
{
- S32 loc = TYPE_NORMAL;
+ AttributeType loc = TYPE_NORMAL;
void* ptr = (void*)(base + mOffsets[TYPE_NORMAL]);
- glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr);
+ glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr);
}
if (data_mask & MAP_TEXCOORD3)
{
- S32 loc = TYPE_TEXCOORD3;
+ AttributeType loc = TYPE_TEXCOORD3;
void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]);
- glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr);
+ glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr);
}
if (data_mask & MAP_TEXCOORD2)
{
- S32 loc = TYPE_TEXCOORD2;
+ AttributeType loc = TYPE_TEXCOORD2;
void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]);
- glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr);
+ glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr);
}
if (data_mask & MAP_TEXCOORD1)
{
- S32 loc = TYPE_TEXCOORD1;
+ AttributeType loc = TYPE_TEXCOORD1;
void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD1]);
- glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr);
+ glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr);
}
if (data_mask & MAP_TANGENT)
{
- S32 loc = TYPE_TANGENT;
+ AttributeType loc = TYPE_TANGENT;
void* ptr = (void*)(base + mOffsets[TYPE_TANGENT]);
- glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr);
+ glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr);
}
if (data_mask & MAP_TEXCOORD0)
{
- S32 loc = TYPE_TEXCOORD0;
+ AttributeType loc = TYPE_TEXCOORD0;
void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]);
- glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr);
+ glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr);
}
if (data_mask & MAP_COLOR)
{
- S32 loc = TYPE_COLOR;
+ 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]);
- glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr);
+ glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr);
}
if (data_mask & MAP_EMISSIVE)
{
- S32 loc = TYPE_EMISSIVE;
+ AttributeType loc = TYPE_EMISSIVE;
void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]);
- glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
+ 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;
- glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
+ glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
}
}
if (data_mask & MAP_WEIGHT)
{
- S32 loc = TYPE_WEIGHT;
+ AttributeType loc = TYPE_WEIGHT;
void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]);
- glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr);
+ glVertexAttribPointer(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr);
}
if (data_mask & MAP_WEIGHT4)
{
- S32 loc = TYPE_WEIGHT4;
+ AttributeType loc = TYPE_WEIGHT4;
void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT4]);
- glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr);
+ glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr);
}
if (data_mask & MAP_CLOTHWEIGHT)
{
- S32 loc = TYPE_CLOTHWEIGHT;
+ AttributeType loc = TYPE_CLOTHWEIGHT;
void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]);
- glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
+ glVertexAttribPointer(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
}
if (data_mask & MAP_TEXTURE_INDEX)
{
-#if !LL_DARWIN
- S32 loc = TYPE_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);
-#endif
}
if (data_mask & MAP_VERTEX)
{
- S32 loc = TYPE_VERTEX;
+ AttributeType loc = TYPE_VERTEX;
void* ptr = (void*)(base + mOffsets[TYPE_VERTEX]);
- glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
+ glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
}
}
-LLVertexBuffer::MappedRegion::MappedRegion(S32 type, S32 index, S32 count)
-: mType(type), mIndex(index), mCount(count)
-{
- mEnd = mIndex+mCount;
-}
+void LLVertexBuffer::setPositionData(const LLVector4a* data)
+{
+ llassert(sGLRenderBuffer == mGLBuffer);
+ flush_vbo(GL_ARRAY_BUFFER, 0, sizeof(LLVector4a) * getNumVerts()-1, (U8*) data);
+}
+
+void LLVertexBuffer::setTexCoordData(const LLVector2* data)
+{
+ llassert(sGLRenderBuffer == mGLBuffer);
+ flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TEXCOORD0], mOffsets[TYPE_TEXCOORD0] + sTypeSize[TYPE_TEXCOORD0] * getNumVerts() - 1, (U8*)data);
+}
+
+void LLVertexBuffer::setColorData(const LLColor4U* data)
+{
+ llassert(sGLRenderBuffer == mGLBuffer);
+ flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_COLOR], mOffsets[TYPE_COLOR] + sTypeSize[TYPE_COLOR] * getNumVerts() - 1, (U8*) data);
+}
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index 3b3fe44984..f2d146d4bb 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -51,69 +51,18 @@
//============================================================================
-// gl name pools for dynamic and streaming buffers
-class LLVBOPool
-{
-public:
- static U32 sBytesPooled;
- static U32 sIndexBytesPooled;
-
- LLVBOPool(U32 vboUsage, U32 vboType);
-
- const U32 mUsage;
- const U32 mType;
-
- //size MUST be a power of 2
- U8* allocate(U32& name, U32 size, bool for_seed = false);
-
- //size MUST be the size provided to allocate that returned the given name
- void release(U32 name, U8* buffer, U32 size);
-
- //batch allocate buffers to be provided to the application on demand
- void seedPool();
-
- //destroy all records in mFreeList
- void cleanup();
-
- U32 genBuffer();
- void deleteBuffer(U32 name);
-
- class Record
- {
- public:
- U32 mGLName;
- U8* mClientData;
- };
-
- typedef std::list<Record> record_list_t;
- std::vector<record_list_t> mFreeList;
- std::vector<U32> mMissCount;
-
- //used to avoid calling glGenBuffers for every VBO creation
- static U32 sNamePool[1024];
- static U32 sNameIdx;
-};
-
-
-//============================================================================
// base class
class LLPrivateMemoryPool;
-class LLVertexBuffer : public LLRefCount
+class LLVertexBuffer final : public LLRefCount
{
public:
- class MappedRegion
+ struct MappedRegion
{
- public:
- S32 mType;
- S32 mIndex;
- S32 mCount;
- S32 mEnd;
-
- MappedRegion(S32 type, S32 index, S32 count);
+ U32 mStart;
+ U32 mEnd;
};
LLVertexBuffer(const LLVertexBuffer& rhs)
- : mUsage(rhs.mUsage)
{
*this = rhs;
}
@@ -124,50 +73,31 @@ public:
return *this;
}
- static LLVBOPool sStreamVBOPool;
- static LLVBOPool sDynamicVBOPool;
- static LLVBOPool sDynamicCopyVBOPool;
- static LLVBOPool sStreamIBOPool;
- static LLVBOPool sDynamicIBOPool;
-
- static std::list<U32> sAvailableVAOName;
- static U32 sCurVAOName;
-
- static bool sUseStreamDraw;
- static bool sUseVAO;
- static bool sPreferStreamDraw;
-
- static void seedPools();
-
- static U32 getVAOName();
- static void releaseVAOName(U32 name);
-
- static void initClass(bool use_vbo, bool no_vbo_mapping);
+ static void initClass(LLWindow* window);
static void cleanupClass();
static void setupClientArrays(U32 data_mask);
static void drawArrays(U32 mode, const std::vector<LLVector3>& pos);
- static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp);
+ static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, U32 num_indices, const U16* indicesp);
static void unbind(); //unbind any bound vertex buffer
//get the size of a vertex with the given typemask
- static S32 calcVertexSize(const U32& typemask);
+ static U32 calcVertexSize(const U32& typemask);
//get the size of a buffer with the given typemask and vertex count
//fill offsets with the offset of each vertex component array into the buffer
// indexed by the following enum
- static S32 calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices);
+ static U32 calcOffsets(const U32& typemask, U32* offsets, U32 num_vertices);
//WARNING -- when updating these enums you MUST
// 1 - update LLVertexBuffer::sTypeSize
- // 2 - add a strider accessor
- // 3 - modify LLVertexBuffer::setupVertexBuffer
- // 4 - modify LLVertexBuffer::setupClientArray
- // 5 - modify LLViewerShaderMgr::mReservedAttribs
- // 6 - update LLVertexBuffer::setupVertexArray
-
+ // 2 - update LLVertexBuffer::vb_type_name
+ // 3 - add a strider accessor
+ // 4 - modify LLVertexBuffer::setupVertexBuffer
+ // 6 - modify LLViewerShaderMgr::mReservedAttribs
+
// clang-format off
- enum { // Shader attribute name, set in LLShaderMgr::initAttribsAndUniforms()
+ enum AttributeType { // Shader attribute name, set in LLShaderMgr::initAttribsAndUniforms()
TYPE_VERTEX = 0, // "position"
TYPE_NORMAL, // "normal"
TYPE_TEXCOORD0, // "texcoord0"
@@ -195,7 +125,6 @@ public:
MAP_TEXCOORD3 = (1<<TYPE_TEXCOORD3),
MAP_COLOR = (1<<TYPE_COLOR),
MAP_EMISSIVE = (1<<TYPE_EMISSIVE),
- // These use VertexAttribPointer and should possibly be made generic
MAP_TANGENT = (1<<TYPE_TANGENT),
MAP_WEIGHT = (1<<TYPE_WEIGHT),
MAP_WEIGHT4 = (1<<TYPE_WEIGHT4),
@@ -206,48 +135,37 @@ public:
protected:
friend class LLRender;
- virtual ~LLVertexBuffer(); // use unref()
+ ~LLVertexBuffer(); // use unref()
- virtual void setupVertexBuffer(U32 data_mask);
- void setupVertexBufferFast(U32 data_mask);
+ void setupVertexBuffer();
- void setupVertexArray();
-
void genBuffer(U32 size);
void genIndices(U32 size);
- bool bindGLBuffer(bool force_bind = false);
- bool bindGLBufferFast();
- bool bindGLIndices(bool force_bind = false);
- bool bindGLIndicesFast();
- bool bindGLArray();
- void releaseBuffer();
- void releaseIndices();
bool createGLBuffer(U32 size);
bool createGLIndices(U32 size);
void destroyGLBuffer();
void destroyGLIndices();
- bool updateNumVerts(S32 nverts);
- bool updateNumIndices(S32 nindices);
- void unmapBuffer();
-
+ bool updateNumVerts(U32 nverts);
+ bool updateNumIndices(U32 nindices);
+
public:
- LLVertexBuffer(U32 typemask, S32 usage);
+ LLVertexBuffer(U32 typemask);
- // map for data access
- U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range);
- U8* mapIndexBuffer(S32 index, S32 count, bool map_range);
+ // allocate buffer
+ bool allocateBuffer(U32 nverts, U32 nindices);
- void bindForFeedback(U32 channel, U32 type, U32 index, U32 count);
+ // map for data access (see also getFooStrider below)
+ U8* mapVertexBuffer(AttributeType type, U32 index, S32 count = -1);
+ U8* mapIndexBuffer(U32 index, S32 count = -1);
+ void unmapBuffer();
// set for rendering
- virtual void setBuffer(U32 data_mask); // calls setupVertexBuffer() if data_mask is not 0
- void setBufferFast(U32 data_mask); // calls setupVertexBufferFast(), assumes data_mask is not 0 among other assumptions
-
- void flush(); //flush pending data to GL memory
- // allocate buffer
- bool allocateBuffer(S32 nverts, S32 nindices, bool create);
- virtual bool resizeBuffer(S32 newnverts, S32 newnindices);
-
+ // assumes (and will assert on) the following:
+ // - this buffer has no pending unampBuffer call
+ // - a shader is currently bound
+ // - This buffer has sufficient attributes within it to satisfy the needs of the currently bound shader
+ void setBuffer();
+
// Only call each getVertexPointer, etc, once before calling unmapBuffer()
// call unmapBuffer() after calls to getXXXStrider() before any cals to setBuffer()
// example:
@@ -255,119 +173,104 @@ public:
// vb->getNormalStrider(norms);
// setVertsNorms(verts, norms);
// vb->unmapBuffer();
- bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getVertexStrider(LLStrider<LLVector4a>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getIndexStrider(LLStrider<U16>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getTangentStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getTangentStrider(LLStrider<LLVector4a>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getEmissiveStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getWeightStrider(LLStrider<F32>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getVertexStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
+ bool getVertexStrider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);
+ bool getIndexStrider(LLStrider<U16>& strider, U32 index=0, S32 count = -1);
+ bool getTexCoord0Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
+ bool getTexCoord1Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
+ bool getTexCoord2Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
+ bool getNormalStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
+ bool getTangentStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
+ bool getTangentStrider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);
+ bool getColorStrider(LLStrider<LLColor4U>& strider, U32 index=0, S32 count = -1);
+ bool getEmissiveStrider(LLStrider<LLColor4U>& strider, U32 index=0, S32 count = -1);
+ bool getWeightStrider(LLStrider<F32>& strider, U32 index=0, S32 count = -1);
+ bool getWeight4Strider(LLStrider<LLVector4>& strider, U32 index=0, S32 count = -1);
+ bool getClothWeightStrider(LLStrider<LLVector4>& strider, U32 index=0, S32 count = -1);
+ bool getBasecolorTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
+ bool getNormalTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
+ bool getMetallicRoughnessTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
+ bool getEmissiveTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
+ void setPositionData(const LLVector4a* data);
+ void setTexCoordData(const LLVector2* data);
+ void setColorData(const LLColor4U* data);
+
- bool useVBOs() const;
- bool isEmpty() const { return mEmpty; }
- bool isLocked() const { return mVertexLocked || mIndexLocked; }
- S32 getNumVerts() const { return mNumVerts; }
- S32 getNumIndices() const { return mNumIndices; }
+ U32 getNumVerts() const { return mNumVerts; }
+ U32 getNumIndices() const { return mNumIndices; }
- U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; }
- U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; }
U32 getTypeMask() const { return mTypeMask; }
- bool hasDataType(S32 type) const { return ((1 << type) & getTypeMask()); }
- S32 getSize() const;
- S32 getIndicesSize() const { return mIndicesSize; }
+ bool hasDataType(AttributeType type) const { return ((1 << type) & getTypeMask()); }
+ U32 getSize() const { return mSize; }
+ U32 getIndicesSize() const { return mIndicesSize; }
U8* getMappedData() const { return mMappedData; }
U8* getMappedIndices() const { return mMappedIndexData; }
- S32 getOffset(S32 type) const { return mOffsets[type]; }
- S32 getUsage() const { return mUsage; }
- bool isWriteable() const { return (mMappable || mUsage == GL_STREAM_DRAW_ARB) ? true : false; }
-
+ U32 getOffset(AttributeType type) const { return mOffsets[type]; }
+
+ // these functions assume (and assert on) the current VBO being bound
+ // Detailed error checking can be enabled by setting gDebugGL to true
void draw(U32 mode, U32 count, U32 indices_offset) const;
void drawArrays(U32 mode, U32 offset, U32 count) const;
- void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const;
-
- //implementation for inner loops that does no safety checking
- void drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const;
+ void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const;
//for debugging, validate data in given range is valid
- void validateRange(U32 start, U32 end, U32 count, U32 offset) const;
+ bool validateRange(U32 start, U32 end, U32 count, U32 offset) const;
+ #ifdef LL_PROFILER_ENABLE_RENDER_DOC
+ void setLabel(const char* label);
+ #endif
protected:
- S32 mNumVerts; // Number of vertices allocated
- S32 mNumIndices; // Number of indices allocated
-
- ptrdiff_t mAlignedOffset;
- ptrdiff_t mAlignedIndexOffset;
- S32 mSize;
- S32 mIndicesSize;
- U32 mTypeMask;
-
- const S32 mUsage; // GL usage
-
- U32 mGLBuffer; // GL VBO handle
- U32 mGLIndices; // GL IBO handle
- U32 mGLArray; // GL VAO handle
-
- U8* mMappedData; // pointer to currently mapped data (NULL if unmapped)
- U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped)
-
- U32 mMappedDataUsingVBOs : 1;
- U32 mMappedIndexDataUsingVBOs : 1;
- U32 mVertexLocked : 1; // if true, vertex buffer is being or has been written to in client memory
- U32 mIndexLocked : 1; // if true, index buffer is being or has been written to in client memory
- U32 mFinal : 1; // if true, buffer can not be mapped again
- U32 mEmpty : 1; // if true, client buffer is empty (or NULL). Old values have been discarded.
-
- mutable bool mMappable; // if true, use memory mapping to upload data (otherwise doublebuffer and use glBufferSubData)
+ U32 mGLBuffer = 0; // GL VBO handle
+ U32 mGLIndices = 0; // GL IBO handle
+ U32 mNumVerts = 0; // Number of vertices allocated
+ U32 mNumIndices = 0; // Number of indices allocated
+ U32 mOffsets[TYPE_MAX]; // byte offsets into mMappedData of each attribute
- S32 mOffsets[TYPE_MAX];
+ U8* mMappedData = nullptr; // pointer to currently mapped data (NULL if unmapped)
+ U8* mMappedIndexData = nullptr; // pointer to currently mapped indices (NULL if unmapped)
- std::vector<MappedRegion> mMappedVertexRegions;
- std::vector<MappedRegion> mMappedIndexRegions;
-
- mutable LLGLFence* mFence;
-
- void placeFence() const;
- void waitFence() const;
+ U32 mTypeMask = 0; // bitmask of present vertex attributes
+
+ U32 mSize = 0; // size in bytes of mMappedData
+ U32 mIndicesSize = 0; // size in bytes of mMappedIndexData
- static S32 determineUsage(S32 usage);
+ std::vector<MappedRegion> mMappedVertexRegions; // list of mMappedData byte ranges that must be sent to GL
+ std::vector<MappedRegion> mMappedIndexRegions; // list of mMappedIndexData byte ranges that must be sent to GL
private:
- static LLPrivateMemoryPool* sPrivatePoolp;
+ // DEPRECATED
+ // These function signatures are deprecated, but for some reason
+ // there are classes in an external package that depend on LLVertexBuffer
+
+ // TODO: move these classes into viewer repository
+ friend class LLNavShapeVBOManager;
+ friend class LLNavMeshVBOManager;
+
+ LLVertexBuffer(U32 typemask, U32 usage)
+ : LLVertexBuffer(typemask)
+ {}
+
+ bool allocateBuffer(S32 nverts, S32 nindices, BOOL create) { return allocateBuffer(nverts, nindices); }
public:
- static S32 sCount;
- static S32 sGLCount;
- static S32 sMappedCount;
- static bool sMapped;
- typedef std::list<LLVertexBuffer*> buffer_list_t;
-
- static bool sDisableVBOMapping; //disable glMapBufferARB
- static bool sEnableVBOs;
- static const S32 sTypeSize[TYPE_MAX];
+
+ static U64 getBytesAllocated();
+ static const U32 sTypeSize[TYPE_MAX];
static const U32 sGLMode[LLRender::NUM_MODES];
static U32 sGLRenderBuffer;
- static U32 sGLRenderArray;
static U32 sGLRenderIndices;
- static bool sVBOActive;
- static bool sIBOActive;
static U32 sLastMask;
- static U32 sAllocatedBytes;
- static U32 sAllocatedIndexBytes;
static U32 sVertexCount;
- static U32 sIndexCount;
- static U32 sBindCount;
- static U32 sSetCount;
};
+#ifdef LL_PROFILER_ENABLE_RENDER_DOC
+#define LL_LABEL_VERTEX_BUFFER(buf, name) buf->setLabel(name)
+#else
+#define LL_LABEL_VERTEX_BUFFER(buf, name)
+#endif
+
#endif // LL_LLVERTEXBUFFER_H