diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 9ba730133e..67d3b30c18 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -54,6 +54,8 @@ using std::string;
GLuint LLGLSLShader::sCurBoundShader = 0;
LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL;
S32 LLGLSLShader::sIndexedTextureChannels = 0;
+S32 LLGLSLShader::sIndexedGLTFChannels = 0;
+bool LLGLSLShader::sIndexedLegacyMaterials = false;
U32 LLGLSLShader::sMaxGLTFMaterials = 0;
U32 LLGLSLShader::sMaxGLTFNodes = 0;
bool LLGLSLShader::sProfileEnabled = false;
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 18cc5c4ddd..8c04063a9a 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -181,6 +181,17 @@ class LLGLSLShader
static LLGLSLShader* sCurBoundShaderPtr;
static S32 sIndexedTextureChannels;
+ // Number of GLTF PBR materials that can be batched into one indexed draw call.
+ // Each material consumes four texture units (base color, normal, ORM, emissive),
+ // so this is roughly (available fragment texture units) / 4. See
+ // PASS_GLTF_PBR_INDEXED and LLVolumeGeometryManager::genDrawInfo.
+ static S32 sIndexedGLTFChannels;
+
+ // True once the indexed legacy (Blinn-Phong) material programs have loaded.
+ // Gates indexed POOL_MATERIALS batching (shares sIndexedGLTFChannels for the
+ // per-slot stride); independent so a material-shader failure doesn't disable PBR.
+ static bool sIndexedLegacyMaterials;
+
static U32 sMaxGLTFMaterials;
static U32 sMaxGLTFNodes;
diff --git a/indra/newview/app_settings/settings_alchemy.xml b/indra/newview/app_settings/settings_alchemy.xml
index 48f2c098e5..960048deae 100644
--- a/indra/newview/app_settings/settings_alchemy.xml
+++ b/indra/newview/app_settings/settings_alchemy.xml
@@ -1235,6 +1235,17 @@
Value
1
+ RenderGLTFPBRBatching
+
RenderBloomThreshold